committee-minitest-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: faab30b61f2892d598568e3c3c8abb59972086807f79fca4f9857c55ad5bb19e
4
+ data.tar.gz: d6bb5ea070d165849d6700c13ccb01cf8b8ce83184c7413d5755ae33b4f07a92
5
+ SHA512:
6
+ metadata.gz: c7c38ef14264613355c0d7d815caa4093dbc061937967d603b6ff4862a3e87bc4d5d15e666229bff404a4dcc10e5f80d6263aeefd7655d974ab2f1a9cfae70b5
7
+ data.tar.gz: caefccc65dd3d742b59b0e05926d89e4eba39f3b031bc17ee6125ceabfe04492d67586f42ddbc8ec00e4518f55f0ce6243e2478a38d6f48d83a4932873d42353
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in committee-minitest-rails.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Committee::Minitest::Rails
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/committee/minitest/rails`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/committee-minitest-rails.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Coverage
5
+ class HTMLFormatter
6
+ attr_reader :report
7
+
8
+ delegate :responses,
9
+ :covered_responses,
10
+ :missed_responses,
11
+ :covered_percent,
12
+ to: :report
13
+
14
+ def initialize(report)
15
+ @report = report
16
+ end
17
+
18
+ def format
19
+ File.open(File.join(output_path, "index.html"), "wb") do |file|
20
+ template = ERB.new(File.read(File.join(File.dirname(__FILE__), "index.html.erb")))
21
+
22
+ file.puts template.result(binding)
23
+ end
24
+ end
25
+
26
+ def project_name
27
+ Committee::Minitest::Rails.project_name
28
+ end
29
+
30
+ def output_path
31
+ @output_path ||= File.expand_path("api-coverage").tap do |path|
32
+ FileUtils.mkdir_p path
33
+ end
34
+ end
35
+
36
+ def assets_path(name)
37
+ File.join("./assets", name)
38
+ end
39
+
40
+ def asset_output_path
41
+ @asset_output_path ||= File.join(output_path, "assets").tap do |path|
42
+ FileUtils.mkdir_p(path)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,78 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns='http://www.w3.org/1999/xhtml'>
3
+ <head>
4
+ <title>API coverage for <%= project_name %></title>
5
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
6
+ <style>
7
+ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; }
8
+
9
+ body { font-family: "Lucida Grande", Helvetica, "Helvetica Neue", Arial, sans-serif; padding: 12px; background-color: #333; }
10
+ table { width: 100%; }
11
+ #content { clear: left; background-color: white; border: 2px solid #ddd; border-top: 8px solid #ddd; padding: 18px; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-topright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-right-radius: 5px; }
12
+ .response_list { margin-bottom: 18px; }
13
+ .response_list--responsive { overflow-x: auto; overflow-y: hidden; }
14
+ tr, td { margin: 0; padding: 0; }
15
+ th { white-space: nowrap; }
16
+ td { padding: 4px 8px; }
17
+ td.strong { font-weight: bold; }
18
+ #footer { color: #ddd; font-size: 12px; font-weight: bold; margin-top: 12px; text-align: right; }
19
+ .green { color: #090; }
20
+ .red { color: #900; }
21
+ .yellow { color: #da0; }
22
+ .blue { color: blue; }
23
+ .align-right { text-align: right; }
24
+ thead th { background: white; }
25
+ thead { border-bottom: 1px solid #111; }
26
+ tbody tr:nth-child(even) { background-color: #f1f1f1; }
27
+ </style>
28
+ </head>
29
+
30
+ <body>
31
+ <div>
32
+ <div id="content">
33
+ <div class="response_list_container">
34
+ <h2>
35
+ <span class="group_name"><%= project_name %> API Coverage</span>
36
+ (<span class="covered_percent"><%= covered_percent %>%</span> covered)
37
+ </h2>
38
+
39
+ <div>
40
+ <b><%= responses.length %></b> responses in total.
41
+ </div>
42
+
43
+ <div class="t-line-summary">
44
+ <span class="green"><b><%= covered_responses %></b> responses covered</span> and
45
+ <span class="red"><b><%= missed_responses %></b> responses missed. </span>
46
+ </div>
47
+
48
+ <div class="response_list--responsive">
49
+ <table class="response_list">
50
+ <thead>
51
+ <tr>
52
+ <th>Path</th>
53
+ <th class="align-right">Method</th>
54
+ <th class="align-right">Status</th>
55
+ <th class="align-right">Covered</th>
56
+ </tr>
57
+ </thead>
58
+ <tbody>
59
+ <% responses.each do |response| %>
60
+ <tr class="t-file">
61
+ <td class="strong t-file__name"><%= response[:path] %></td>
62
+ <td class="align-right"><%= response[:method].upcase %></td>
63
+ <td class="align-right"><%= response[:status] %></td>
64
+ <td class="<%= response[:is_covered] ? "green" : "red" %> strong align-right"><%= response[:is_covered] ? "Covered" : "Missed" %></td>
65
+ </tr>
66
+ <% end %>
67
+ </tbody>
68
+ </table>
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ <div id="footer">
74
+ Generated by Committee Minitest Rails Coverage
75
+ </div>
76
+ </div>
77
+ </body>
78
+ </html>
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Coverage
5
+ class Report
6
+ attr_reader :report
7
+
8
+ def initialize(report)
9
+ @report = Committee::Test::SchemaCoverage.flatten_report(report)
10
+ end
11
+
12
+ def responses
13
+ @responses ||= begin
14
+ path_filter = unless Committee::Minitest::Rails.path_filter.nil?
15
+ Regexp.new Committee::Minitest::Rails.path_filter
16
+ end
17
+
18
+ report[:responses]
19
+ .select { |response| path_filter.nil? || path_filter.match?(response[:path]) }
20
+ .sort_by { |response| response[:path] }
21
+ end
22
+ end
23
+
24
+ def covered_responses
25
+ @covered_responses ||= responses.count { |response| response[:is_covered] }
26
+ end
27
+
28
+ def missed_responses
29
+ @missed_responses ||= responses.count { |response| !response[:is_covered] }
30
+ end
31
+
32
+ def covered_percent
33
+ format("%.2f", covered_responses.to_f * 100 / responses.count)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Minitest
5
+ module Rails
6
+ class RequestObject
7
+ delegate_missing_to :@request
8
+
9
+ def initialize(request)
10
+ @request = request
11
+ end
12
+
13
+ def path
14
+ URI.parse(@request.original_fullpath).path
15
+ end
16
+
17
+ def path_info
18
+ URI.parse(@request.original_fullpath).path
19
+ end
20
+
21
+ def request_method
22
+ @request.env["action_dispatch.original_request_method"] ||
23
+ @request.request_method
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Minitest
5
+ module Rails
6
+ module TestMethods
7
+ include ::Committee::Test::Methods
8
+
9
+ def committee_options
10
+ @committee_options ||= begin
11
+ schema = Committee::Drivers.load_from_file(
12
+ Committee::Minitest::Rails.schema_path,
13
+ parser_options: { strict_reference_validation: true }
14
+ )
15
+ {
16
+ schema: schema,
17
+ schema_coverage: Committee::Test::SchemaCoverage.new(schema)
18
+ }
19
+ end
20
+ end
21
+
22
+ def schema_coverage
23
+ committee_options[:schema_coverage]
24
+ end
25
+
26
+ def request_object
27
+ @request_object ||= RequestObject
28
+ .new(integration_session.request)
29
+ end
30
+
31
+ def response_data
32
+ [
33
+ integration_session.response.status,
34
+ integration_session.response.headers,
35
+ integration_session.response.body
36
+ ]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Minitest
5
+ module Rails
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rails/version"
4
+ require_relative "rails/test_methods"
5
+ require_relative "rails/request_object"
6
+ require_relative "../coverage/html_formatter"
7
+ require_relative "../coverage/report"
8
+
9
+ module Committee
10
+ module Minitest
11
+ module Rails
12
+ class Error < StandardError; end
13
+
14
+ mattr_accessor :schema_path, :path_filter
15
+
16
+ def self.project_name
17
+ @project_name ||= File.basename(root.split("/").last).capitalize.tr("_", " ")
18
+ end
19
+
20
+ def self.root
21
+ @root ||= File.expand_path(Dir.getwd)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Minitest
4
+ class CommitteeCoverageReporter < AbstractReporter
5
+ attr_accessor :schema_coverage
6
+
7
+ def initialize
8
+ @schema_coverage = {}
9
+ end
10
+
11
+ def record(result)
12
+ @schema_coverage = Committee::Test::SchemaCoverage.merge_report(
13
+ @schema_coverage,
14
+ result.committee_coverage
15
+ )
16
+ end
17
+
18
+ def report
19
+ report = Committee::Coverage::Report.new(@schema_coverage)
20
+ puts "API coverage: #{report.covered_percent}"
21
+ Committee::Coverage::HTMLFormatter.new(report).format
22
+ end
23
+ end
24
+
25
+ def self.plugin_committee_init(options)
26
+ self.reporter << CommitteeCoverageReporter.new
27
+ end
28
+
29
+ module ResultExtension
30
+ def from(runnable)
31
+ super.tap do |r|
32
+ r.committee_coverage =
33
+ if runnable.respond_to? :schema_coverage
34
+ runnable.schema_coverage.report
35
+ else
36
+ {}
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ Result.singleton_class.prepend(ResultExtension)
43
+ Result.attr_accessor :committee_coverage
44
+ end
@@ -0,0 +1,8 @@
1
+ module Committee
2
+ module Minitest
3
+ module Rails
4
+ VERSION: String
5
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
6
+ end
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: committee-minitest-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Pigeon
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-07-10 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - eric.r.pigeon@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rspec"
21
+ - Gemfile
22
+ - README.md
23
+ - Rakefile
24
+ - lib/committee/coverage/html_formatter.rb
25
+ - lib/committee/coverage/index.html.erb
26
+ - lib/committee/coverage/report.rb
27
+ - lib/committee/minitest/rails.rb
28
+ - lib/committee/minitest/rails/request_object.rb
29
+ - lib/committee/minitest/rails/test_methods.rb
30
+ - lib/committee/minitest/rails/version.rb
31
+ - lib/minitest/committee_plugin.rb
32
+ - sig/committee/minitest/rails.rbs
33
+ homepage:
34
+ licenses: []
35
+ metadata:
36
+ source_code_uri: https://github.com/eric-pigeon/committee-minitest-rails
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 2.6.0
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubygems_version: 3.1.6
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: Committee integration with Rails and Minitest
56
+ test_files: []