diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c8e63c9..8fe5630 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,9 @@ jobs: gem uninstall bundler -a -x || true - name: Install Bundler run: | - if [[ "${{ matrix.ruby-version }}" == "2.6" || "${{ matrix.ruby-version }}" == "2.7" ]]; then + if [[ "${{ matrix.ruby-version }}" == "2.5" ]]; then + gem install bundler -v "~> 2.3.27" + elif [[ "${{ matrix.ruby-version }}" == "2.6" || "${{ matrix.ruby-version }}" == "2.7" ]]; then gem install bundler -v "~> 2.4.0" else gem install bundler diff --git a/CHANGELOG.md b/CHANGELOG.md index f6b51f9..e39a04e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # main ([unreleased](https://github.com/fastruby/rails_stats/compare/v1.0.2...main)) -* +* [BUGFIX: Fix JSON output missing Code and Tests total count](https://github.com/fastruby/rails_stats/pull/40) +* Update README examples # v2.0.1 ([commits](https://github.com/fastruby/rails_stats/compare/v2.0.0...v2.0.1)) diff --git a/Gemfile b/Gemfile index 7928524..c0f7f59 100644 --- a/Gemfile +++ b/Gemfile @@ -5,10 +5,10 @@ gemspec group :development, :test do gem "bundler", ">= 1.6", "< 3.0" gem "byebug" - gem "codecov" + gem "codecov", "~> 0.6.0" gem "minitest" gem "minitest-around" gem "minitest-spec-context" - gem "simplecov" + gem "simplecov", "~> 0.21" gem "simplecov-console" end diff --git a/README.md b/README.md index ac3c3ab..e94c4fb 100644 --- a/README.md +++ b/README.md @@ -23,26 +23,46 @@ $ rake stats\[/path/to/app/\] Directory: /path/to/app/ -+----------------------+-------+-------+---------+---------+-----+-------+ -| Name | Lines | LOC | Classes | Methods | M/C | LOC/M | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Controllers | 1848 | 1483 | 32 | 174 | 5 | 6 | -| Helpers | 2257 | 1892 | 45 | 245 | 5 | 5 | -| Jobs | 399 | 295 | 11 | 33 | 3 | 6 | -| Models | 4584 | 3509 | 61 | 526 | 8 | 4 | -| Observers | 42 | 22 | 2 | 5 | 2 | 2 | -| Libraries | 2987 | 2272 | 30 | 287 | 9 | 5 | -| Configuration | 1233 | 669 | 4 | 17 | 4 | 37 | -| Spec Support | 1416 | 1152 | 4 | 30 | 7 | 36 | -| Integration Tests | 91 | 73 | 0 | 1 | 0 | 71 | -| Lib Tests | 101 | 83 | 0 | 1 | 0 | 81 | -| Model Tests | 3397 | 2522 | 0 | 18 | 0 | 138 | -| Cucumber Support | 739 | 521 | 0 | 1 | 0 | 519 | -| Cucumber Features | 2711 | 2487 | 29 | 145 | 5 | 15 | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Total | 21805 | 16980 | 218 | 1483 | 6 | 9 | -+----------------------+-------+-------+---------+---------+-----+-------+ - Code LOC: 10142 Test LOC: 6838 Code to Test Ratio: 1:0.7 ++-----------------------|------------|----------------+ +| Name | Total Deps | 1st Level Deps | ++-----------------------|------------|----------------+ +| simplecov-console | 7 | 3 | +| codecov | 5 | 2 | +| rails_stats | 4 | 2 | +| simplecov | 3 | 3 | +| minitest-around | 1 | 1 | +| bundler | 0 | 0 | +| byebug | 0 | 0 | +| minitest | 0 | 0 | +| minitest-spec-context | 0 | 0 | ++-----------------------|------------|----------------+ + + Declared Gems 9 + Total Gems 18 + Unpinned Versions 8 + Github Refs 0 + ++----------------------+---------+---------+---------+---------+---------+-----+-------+ +| Name | Files | Lines | LOC | Classes | Methods | M/C | LOC/M | ++----------------------+---------+---------+---------+---------+---------+-----+-------+ +| Channels | 2 | 8 | 8 | 2 | 0 | 0 | 0 | +| Configuration | 19 | 417 | 111 | 1 | 0 | 0 | 0 | +| Controllers | 1 | 7 | 6 | 1 | 1 | 1 | 4 | +| Helpers | 1 | 3 | 3 | 0 | 0 | 0 | 0 | +| Javascripts | 3 | 27 | 7 | 0 | 0 | 0 | 0 | +| Jobs | 1 | 7 | 2 | 1 | 0 | 0 | 0 | +| Libraries | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| Mailers | 1 | 4 | 4 | 1 | 0 | 0 | 0 | +| Model Tests | 2 | 5 | 4 | 2 | 0 | 0 | 0 | +| Models | 1 | 3 | 3 | 1 | 0 | 0 | 0 | +| Spec Support | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| Test Support | 1 | 1 | 1 | 0 | 0 | 0 | 0 | ++----------------------+---------+---------+---------+---------+---------+-----+-------+ +| Code | 30 | 477 | 145 | 7 | 1 | 0 | 143 | +| Tests | 4 | 7 | 6 | 2 | 0 | 0 | 0 | +| Total | 34 | 484 | 151 | 9 | 1 | 0 | 149 | ++----------------------+---------+---------+---------+---------+---------+-----+-------+ + Code LOC: 145 Test LOC: 6 Code to Test Ratio: 1:0.0 Files: 34 ``` ### Run it on many Rails engines @@ -80,193 +100,88 @@ RailsStats adds more coverage than the default. Here are some open source Rails projects and their output. ```bash -$ bundle exec rake stats[/users/brian/examples/diaspora/] - -Directory: /users/brian/examples/diaspora - -+----------------------+-------+-------+---------+---------+-----+-------+ -| Name | Lines | LOC | Classes | Methods | M/C | LOC/M | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Collections | 259 | 198 | 0 | 56 | 0 | 1 | -| Helpers | 1863 | 1478 | 0 | 218 | 0 | 4 | -| Models | 4694 | 3517 | 55 | 580 | 10 | 4 | -| Pages | 201 | 158 | 0 | 21 | 0 | 5 | -| Controllers | 2797 | 2168 | 40 | 208 | 5 | 8 | -| Mailers | 313 | 263 | 13 | 32 | 2 | 6 | -| Presenters | 516 | 425 | 18 | 71 | 3 | 3 | -| Uploaders | 84 | 63 | 2 | 9 | 4 | 5 | -| Workers | 600 | 399 | 32 | 33 | 1 | 10 | -| Javascripts | 7550 | 4941 | 0 | 741 | 0 | 4 | -| Libraries | 7031 | 4890 | 69 | 701 | 10 | 4 | -| Configuration | 2556 | 833 | 5 | 10 | 2 | 81 | -| Controller Tests | 4628 | 3775 | 0 | 2 | 0 | 1885 | -| Spec Support | 1141 | 900 | 6 | 56 | 9 | 14 | -| Helper Tests | 771 | 615 | 0 | 6 | 0 | 100 | -| Integration Tests | 891 | 647 | 0 | 14 | 0 | 44 | -| Lib Tests | 4076 | 3259 | 2 | 4 | 2 | 812 | -| Other Tests | 120 | 101 | 0 | 0 | 0 | 0 | -| Mailer Tests | 412 | 328 | 0 | 0 | 0 | 0 | -| Model Tests | 6120 | 4964 | 0 | 1 | 0 | 4962 | -| Presenter Tests | 353 | 303 | 0 | 0 | 0 | 0 | -| Worker Tests | 821 | 648 | 0 | 0 | 0 | 0 | -| Cucumber Features | 2157 | 1863 | 47 | 155 | 3 | 10 | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Total | 49954 | 36736 | 289 | 2918 | 10 | 10 | -+----------------------+-------+-------+---------+---------+-----+-------+ - Code LOC: 19333 Test LOC: 17403 Code to Test Ratio: 1:0.9 - - -$ bundle exec rake stats[/users/brian/examples/discourse] - -Directory: /users/brian/examples/discourse - -+----------------------+-------+-------+---------+---------+-----+-------+ -| Name | Lines | LOC | Classes | Methods | M/C | LOC/M | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Controllers | 5005 | 3812 | 56 | 416 | 7 | 7 | -| Helpers | 286 | 218 | 0 | 32 | 0 | 4 | -| Jobs | 1830 | 1343 | 53 | 114 | 2 | 9 | -| Mailers | 438 | 340 | 7 | 24 | 3 | 12 | -| Models | 12378 | 8393 | 123 | 983 | 7 | 6 | -| Serializers | 2809 | 2223 | 73 | 374 | 5 | 3 | -| Services | 1353 | 1060 | 20 | 106 | 5 | 8 | -| Javascripts | 21722 | 13649 | 0 | 1844 | 0 | 5 | -| Libraries | 35298 | 27521 | 189 | 2565 | 13 | 8 | -| Configuration | 1758 | 1179 | 6 | 12 | 2 | 96 | -| Other Tests | 12998 | 9830 | 20 | 41 | 2 | 237 | -| Controller Tests | 7673 | 5911 | 0 | 4 | 0 | 1475 | -| Spec Support | 707 | 560 | 1 | 16 | 16 | 33 | -| Helper Tests | 88 | 71 | 0 | 0 | 0 | 0 | -| Integration Tests | 307 | 235 | 0 | 1 | 0 | 233 | -| Job Tests | 1343 | 1017 | 3 | 9 | 3 | 111 | -| Mailer Tests | 421 | 302 | 0 | 1 | 0 | 300 | -| Model Tests | 11236 | 8599 | 2 | 49 | 24 | 173 | -| Serializer Tests | 297 | 236 | 0 | 2 | 0 | 116 | -| Service Tests | 1767 | 1406 | 0 | 2 | 0 | 701 | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Total | 119714| 87905 | 553 | 6595 | 11 | 11 | -+----------------------+-------+-------+---------+---------+-----+-------+ - Code LOC: 59738 Test LOC: 28167 Code to Test Ratio: 1:0.5 - - -$ bundle exec rake stats[/users/brian/examples/gitlabhq] - -Directory: /users/brian/examples/gitlabhq - -+----------------------+-------+-------+---------+---------+-----+-------+ -| Name | Lines | LOC | Classes | Methods | M/C | LOC/M | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Controllers | 3690 | 2890 | 66 | 384 | 5 | 5 | -| Finders | 428 | 267 | 8 | 27 | 3 | 7 | -| Helpers | 2280 | 1761 | 0 | 222 | 0 | 5 | -| Mailers | 382 | 275 | 1 | 29 | 29 | 7 | -| Models | 6922 | 4680 | 58 | 714 | 12 | 4 | -| Services | 2021 | 1502 | 51 | 149 | 2 | 8 | -| Uploaders | 81 | 62 | 2 | 14 | 7 | 2 | -| Workers | 128 | 99 | 6 | 8 | 1 | 10 | -| Javascripts | 3843 | 2936 | 1 | 534 | 534 | 3 | -| Libraries | 7246 | 4785 | 120 | 438 | 3 | 8 | -| Configuration | 1421 | 782 | 4 | 11 | 2 | 69 | -| Controller Tests | 428 | 334 | 0 | 0 | 0 | 0 | -| Spec Support | 1119 | 715 | 2 | 27 | 13 | 24 | -| Other Tests | 67 | 55 | 0 | 0 | 0 | 0 | -| Feature Tests | 2209 | 1765 | 0 | 8 | 0 | 218 | -| Finder Tests | 281 | 230 | 0 | 0 | 0 | 0 | -| Helper Tests | 1608 | 1255 | 0 | 5 | 0 | 249 | -| Lib Tests | 1459 | 1180 | 1 | 11 | 11 | 105 | -| Mailer Tests | 630 | 478 | 0 | 0 | 0 | 0 | -| Model Tests | 3856 | 2669 | 0 | 10 | 0 | 264 | -| Request Tests | 4229 | 3600 | 0 | 10 | 0 | 358 | -| Routing Tests | 849 | 520 | 0 | 0 | 0 | 0 | -| Service Tests | 1611 | 1307 | 0 | 34 | 0 | 36 | -| Worker Tests | 45 | 35 | 0 | 2 | 0 | 15 | -| Cucumber Features | 6749 | 5734 | 141 | 947 | 6 | 4 | -| Cucumber Support | 6235 | 4980 | 65 | 71 | 1 | 68 | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Total | 59817 | 44896 | 526 | 3655 | 6 | 10 | -+----------------------+-------+-------+---------+---------+-----+-------+ - Code LOC: 20039 Test LOC: 24857 Code to Test Ratio: 1:1.2 - $ bundle exec rake stats[/users/brian/examples/redmine/] -Directory: /users/brian/examples/redmine - -+----------------------+-------+-------+---------+---------+-----+-------+ -| Name | Lines | LOC | Classes | Methods | M/C | LOC/M | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Controllers | 6738 | 5005 | 51 | 416 | 8 | 10 | -| Helpers | 4445 | 3014 | 2 | 281 | 140 | 8 | -| Models | 13221 | 9369 | 86 | 1026 | 11 | 7 | -| Libraries | 19041 | 13499 | 137 | 1147 | 8 | 9 | -| Configuration | 779 | 550 | 14 | 18 | 1 | 28 | -| Integration Tests | 8286 | 6032 | 92 | 202 | 2 | 27 | -| Other Tests | 669 | 521 | 3 | 53 | 17 | 7 | -| Test Support | 1102 | 791 | 8 | 70 | 8 | 9 | -| Functional Tests | 18448 | 14784 | 61 | 1372 | 22 | 8 | -| Unit Tests | 23680 | 18217 | 117 | 1783 | 15 | 8 | -| Helper Tests | 3321 | 2567 | 16 | 171 | 10 | 13 | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Total | 99730 | 74349 | 587 | 6539 | 11 | 9 | -+----------------------+-------+-------+---------+---------+-----+-------+ - Code LOC: 31437 Test LOC: 42912 Code to Test Ratio: 1:1.4 - - -$ bundle exec rake stats[/users/brian/examples/refinerycms] - -Directory: /users/brian/examples/refinerycms - -+----------------------+-------+-------+---------+---------+-----+-------+ -| Name | Lines | LOC | Classes | Methods | M/C | LOC/M | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Controllers | 950 | 748 | 17 | 83 | 4 | 7 | -| Helpers | 399 | 308 | 0 | 28 | 0 | 9 | -| Mailers | 22 | 18 | 1 | 2 | 2 | 7 | -| Models | 846 | 570 | 14 | 86 | 6 | 4 | -| Presenters | 365 | 271 | 8 | 44 | 5 | 4 | -| Javascripts | 717 | 531 | 0 | 52 | 0 | 8 | -| Libraries | 4 | 4 | 0 | 0 | 0 | 0 | -| Gems | 4166 | 2997 | 44 | 372 | 8 | 6 | -| Controller Tests | 207 | 170 | 1 | 1 | 1 | 168 | -| Spec Support | 309 | 243 | 2 | 6 | 3 | 38 | -| Feature Tests | 1907 | 1484 | 0 | 4 | 0 | 369 | -| Lib Tests | 1952 | 1687 | 6 | 4 | 0 | 419 | -| Model Tests | 1323 | 1072 | 0 | 5 | 0 | 212 | -| Helper Tests | 324 | 264 | 0 | 1 | 0 | 262 | -| Presenter Tests | 355 | 299 | 0 | 0 | 0 | 0 | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Total | 13846 | 10666 | 93 | 688 | 7 | 13 | -+----------------------+-------+-------+---------+---------+-----+-------+ - Code LOC: 5447 Test LOC: 5219 Code to Test Ratio: 1:1.0 - - -$ bundle exec rake stats[/users/brian/examples/spree] - -Directory: /users/brian/examples/spree - -+----------------------+-------+-------+---------+---------+-----+-------+ -| Name | Lines | LOC | Classes | Methods | M/C | LOC/M | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Controllers | 4653 | 3800 | 86 | 492 | 5 | 5 | -| Helpers | 1142 | 949 | 0 | 90 | 0 | 8 | -| Models | 9893 | 7308 | 167 | 973 | 5 | 5 | -| Javascripts | 2770 | 2100 | 9 | 416 | 46 | 3 | -| Mailers | 63 | 58 | 5 | 8 | 1 | 5 | -| Libraries | 15 | 14 | 0 | 0 | 0 | 0 | -| Gems | 4690 | 3641 | 35 | 254 | 7 | 12 | -| Controller Tests | 7344 | 6000 | 6 | 19 | 3 | 313 | -| Model Tests | 16747 | 13452 | 20 | 27 | 1 | 496 | -| Request Tests | 32 | 24 | 0 | 0 | 0 | 0 | -| Spec Support | 577 | 427 | 3 | 9 | 3 | 45 | -| Feature Tests | 6079 | 4809 | 0 | 17 | 0 | 280 | -| Helper Tests | 602 | 470 | 2 | 1 | 0 | 468 | -| Lib Tests | 1455 | 1216 | 8 | 11 | 1 | 108 | -| Mailer Tests | 252 | 208 | 0 | 0 | 0 | 0 | -| Other Tests | 33 | 27 | 0 | 0 | 0 | 0 | -+----------------------+-------+-------+---------+---------+-----+-------+ -| Total | 56347 | 44503 | 341 | 2317 | 6 | 17 | -+----------------------+-------+-------+---------+---------+-----+-------+ - Code LOC: 17870 Test LOC: 26633 Code to Test Ratio: 1:1.5 ++-----------------------|------------|----------------+ +| Name | Total Deps | 1st Level Deps | ++-----------------------|------------|----------------+ +| rails | 62 | 13 | +| roadie-rails | 45 | 2 | +| actionpack-xml_parser | 41 | 2 | +| importmap-rails | 41 | 3 | +| propshaft | 41 | 4 | +| stimulus-rails | 41 | 1 | +| rubocop-rails | 28 | 5 | +| rubocop-performance | 15 | 3 | +| html-pipeline | 14 | 2 | +| rails-dom-testing | 14 | 3 | +| rubocop | 14 | 10 | +| bullet | 13 | 2 | +| capybara | 10 | 8 | +| debug | 10 | 2 | +| mail | 7 | 4 | +| selenium-webdriver | 5 | 5 | +| rails_stats | 4 | 2 | +| svg_sprite | 4 | 3 | +| bundle-audit | 3 | 1 | +| listen | 3 | 2 | +| net-imap | 3 | 2 | +| sanitize | 3 | 2 | +| simplecov | 3 | 3 | +| mini_magick | 2 | 2 | +| net-pop | 2 | 1 | +| net-smtp | 2 | 1 | +| rbpdf | 2 | 2 | +| rqrcode | 2 | 2 | +| addressable | 1 | 1 | +| i18n | 1 | 1 | +| mocha | 1 | 1 | +| nokogiri | 1 | 1 | +| puma | 1 | 1 | +| commonmarker | 0 | 0 | +| csv | 0 | 0 | +| ffi | 0 | 0 | +| marcel | 0 | 0 | +| mini_mime | 0 | 0 | +| net-ldap | 0 | 0 | +| rack | 0 | 0 | +| rotp | 0 | 0 | +| rouge | 0 | 0 | +| rubyzip | 0 | 0 | +| tzinfo-data | 0 | 0 | +| yard | 0 | 0 | ++-----------------------|------------|----------------+ + + Declared Gems 45 + Total Gems 144 + Unpinned Versions 19 + Github Refs 0 + ++----------------------+---------+---------+---------+---------+---------+-----+-------+ +| Name | Files | Lines | LOC | Classes | Methods | M/C | LOC/M | ++----------------------+---------+---------+---------+---------+---------+-----+-------+ +| Configuration | 17 | 1090 | 666 | 7 | 14 | 2 | 45 | +| Controllers | 57 | 9042 | 6746 | 60 | 554 | 9 | 10 | +| Functional Tests | 65 | 35754 | 30234 | 65 | 2104 | 32 | 12 | +| Helper Tests | 27 | 5369 | 4090 | 28 | 302 | 10 | 11 | +| Helpers | 49 | 7068 | 5168 | 1 | 413 | 413 | 10 | +| Integration Tests | 98 | 10349 | 7237 | 104 | 297 | 2 | 22 | +| Javascripts | 117 | 6930 | 5362 | 0 | 446 | 0 | 10 | +| Job Tests | 2 | 142 | 94 | 2 | 2 | 1 | 45 | +| Jobs | 3 | 115 | 90 | 3 | 9 | 3 | 8 | +| Libraries | 134 | 18922 | 13178 | 128 | 1167 | 9 | 9 | +| Models | 88 | 20110 | 14528 | 110 | 1532 | 13 | 7 | +| Other Tests | 19 | 2339 | 1525 | 19 | 98 | 5 | 13 | +| Test Support | 16 | 1637 | 1229 | 20 | 142 | 7 | 6 | +| Unit Tests | 147 | 37173 | 28642 | 161 | 2778 | 17 | 8 | +| Validators | 1 | 29 | 10 | 1 | 1 | 1 | 8 | ++----------------------+---------+---------+---------+---------+---------+-----+-------+ +| Code | 466 | 63306 | 45748 | 310 | 4136 | 13 | 9 | +| Tests | 374 | 92763 | 73051 | 399 | 5723 | 14 | 10 | +| Total | 840 | 156069 | 118799 | 709 | 9859 | 13 | 10 | ++----------------------+---------+---------+---------+---------+---------+-----+-------+ + Code LOC: 45748 Test LOC: 73051 Code to Test Ratio: 1:1.6 Files: 840 ``` @@ -277,9 +192,9 @@ If you want to export the details using JSON, you can use this command: ``` $ rake stats\[test/dummy,json\] -Directory: /Users/etagwerker/Projects/fastruby/rails_stats/test/dummy +Directory: /Users/etagwerker/Projects/redmine -[{"name":"Mailers","lines":"4","loc":"4","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Models","lines":"3","loc":"3","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Javascripts","lines":"27","loc":"7","classes":"0","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Jobs","lines":"7","loc":"2","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Controllers","lines":"7","loc":"6","classes":"1","methods":"1","m_over_c":"1","loc_over_m":"4"},{"name":"Helpers","lines":"3","loc":"3","classes":"0","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Channels","lines":"8","loc":"8","classes":"2","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Configuration","lines":"417","loc":"111","classes":"1","methods":"0","m_over_c":"0","loc_over_m":"0"},{"name":"Total","lines":"476","loc":"144","classes":"7","methods":"1","m_over_c":"0","loc_over_m":"142","code_to_test_ratio":"0.0","total":true}] +[{"summary":{"declared":45,"unpinned":19,"total":144,"github":0},"gems":[{"name":"rails","total_dependencies":62,"first_level_dependencies":13,"top_level_dependencies":{},"transitive_dependencies":["actioncable (= 7.2.2.1)","actionmailbox (= 7.2.2.1)","actionmailer (= 7.2.2.1)","actionpack (= 7.2.2.1)","actiontext (= 7.2.2.1)","actionview (= 7.2.2.1)","activejob (= 7.2.2.1)","activemodel (= 7.2.2.1)","activerecord (= 7.2.2.1)","activestorage (= 7.2.2.1)","activesupport (= 7.2.2.1)","bundler (>= 1.15.0)","railties (= 7.2.2.1)","nio4r (~> 2.0)","websocket-driver (>= 0.6.1)","zeitwerk (~> 2.6)","nokogiri (>= 1.8.5)","racc (>= 0)","rack (>= 2.2.4, < 3.2)","rack-session (>= 1.0.1)","rack-test (>= 0.6.3)","rails-dom-testing (~> 2.2)","rails-html-sanitizer (~> 1.6)","useragent (~> 0.16)","builder (~> 3.1)","erubi (~> 1.11)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","loofah (~> 2.21)","crass (~> 1.0.2)","websocket-extensions (>= 0.1.0)","mail (>= 2.8.0)","globalid (>= 0.3.6)","timeout (>= 0.4.0)","marcel (~> 1.0)","mini_mime (>= 0.1.1)","net-imap (>= 0)","net-pop (>= 0)","net-smtp (>= 0)","date (>= 0)","net-protocol (>= 0)","irb (~> 1.13)","rackup (>= 1.0.0)","rake (>= 12.2)","thor (~> 1.0, >= 1.2.2)","pp (>= 0.6.0)","rdoc (>= 4.0.0)","reline (>= 0.4.2)","prettyprint (>= 0)","erb (>= 0)","psych (>= 4.0.0)","stringio (>= 0)","io-console (~> 0.5)"]},{"name":"roadie-rails","total_dependencies":45,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["railties (>= 5.1, < 8.1)","roadie (~> 5.0)","actionpack (= 7.2.2.1)","activesupport (= 7.2.2.1)","irb (~> 1.13)","rackup (>= 1.0.0)","rake (>= 12.2)","thor (~> 1.0, >= 1.2.2)","zeitwerk (~> 2.6)","actionview (= 7.2.2.1)","nokogiri (>= 1.8.5)","racc (>= 0)","rack (>= 2.2.4, < 3.2)","rack-session (>= 1.0.1)","rack-test (>= 0.6.3)","rails-dom-testing (~> 2.2)","rails-html-sanitizer (~> 1.6)","useragent (~> 0.16)","builder (~> 3.1)","erubi (~> 1.11)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","loofah (~> 2.21)","crass (~> 1.0.2)","pp (>= 0.6.0)","rdoc (>= 4.0.0)","reline (>= 0.4.2)","prettyprint (>= 0)","erb (>= 0)","psych (>= 4.0.0)","date (>= 0)","stringio (>= 0)","io-console (~> 0.5)","css_parser (~> 1.4)","addressable (>= 0)","public_suffix (>= 2.0.2, < 7.0)"]},{"name":"actionpack-xml_parser","total_dependencies":41,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["actionpack (>= 5.0)","railties (>= 5.0)","actionview (= 7.2.2.1)","activesupport (= 7.2.2.1)","nokogiri (>= 1.8.5)","racc (>= 0)","rack (>= 2.2.4, < 3.2)","rack-session (>= 1.0.1)","rack-test (>= 0.6.3)","rails-dom-testing (~> 2.2)","rails-html-sanitizer (~> 1.6)","useragent (~> 0.16)","builder (~> 3.1)","erubi (~> 1.11)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","loofah (~> 2.21)","crass (~> 1.0.2)","irb (~> 1.13)","rackup (>= 1.0.0)","rake (>= 12.2)","thor (~> 1.0, >= 1.2.2)","zeitwerk (~> 2.6)","pp (>= 0.6.0)","rdoc (>= 4.0.0)","reline (>= 0.4.2)","prettyprint (>= 0)","erb (>= 0)","psych (>= 4.0.0)","date (>= 0)","stringio (>= 0)","io-console (~> 0.5)"]},{"name":"importmap-rails","total_dependencies":41,"first_level_dependencies":3,"top_level_dependencies":{},"transitive_dependencies":["actionpack (>= 6.0.0)","activesupport (>= 6.0.0)","railties (>= 6.0.0)","actionview (= 7.2.2.1)","nokogiri (>= 1.8.5)","racc (>= 0)","rack (>= 2.2.4, < 3.2)","rack-session (>= 1.0.1)","rack-test (>= 0.6.3)","rails-dom-testing (~> 2.2)","rails-html-sanitizer (~> 1.6)","useragent (~> 0.16)","builder (~> 3.1)","erubi (~> 1.11)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","loofah (~> 2.21)","crass (~> 1.0.2)","irb (~> 1.13)","rackup (>= 1.0.0)","rake (>= 12.2)","thor (~> 1.0, >= 1.2.2)","zeitwerk (~> 2.6)","pp (>= 0.6.0)","rdoc (>= 4.0.0)","reline (>= 0.4.2)","prettyprint (>= 0)","erb (>= 0)","psych (>= 4.0.0)","date (>= 0)","stringio (>= 0)","io-console (~> 0.5)"]},{"name":"propshaft","total_dependencies":41,"first_level_dependencies":4,"top_level_dependencies":{},"transitive_dependencies":["actionpack (>= 7.0.0)","activesupport (>= 7.0.0)","rack (>= 0)","railties (>= 7.0.0)","actionview (= 7.2.2.1)","nokogiri (>= 1.8.5)","racc (>= 0)","rack-session (>= 1.0.1)","rack-test (>= 0.6.3)","rails-dom-testing (~> 2.2)","rails-html-sanitizer (~> 1.6)","useragent (~> 0.16)","builder (~> 3.1)","erubi (~> 1.11)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","loofah (~> 2.21)","crass (~> 1.0.2)","irb (~> 1.13)","rackup (>= 1.0.0)","rake (>= 12.2)","thor (~> 1.0, >= 1.2.2)","zeitwerk (~> 2.6)","pp (>= 0.6.0)","rdoc (>= 4.0.0)","reline (>= 0.4.2)","prettyprint (>= 0)","erb (>= 0)","psych (>= 4.0.0)","date (>= 0)","stringio (>= 0)","io-console (~> 0.5)"]},{"name":"stimulus-rails","total_dependencies":41,"first_level_dependencies":1,"top_level_dependencies":{},"transitive_dependencies":["railties (>= 6.0.0)","actionpack (= 7.2.2.1)","activesupport (= 7.2.2.1)","irb (~> 1.13)","rackup (>= 1.0.0)","rake (>= 12.2)","thor (~> 1.0, >= 1.2.2)","zeitwerk (~> 2.6)","actionview (= 7.2.2.1)","nokogiri (>= 1.8.5)","racc (>= 0)","rack (>= 2.2.4, < 3.2)","rack-session (>= 1.0.1)","rack-test (>= 0.6.3)","rails-dom-testing (~> 2.2)","rails-html-sanitizer (~> 1.6)","useragent (~> 0.16)","builder (~> 3.1)","erubi (~> 1.11)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","loofah (~> 2.21)","crass (~> 1.0.2)","pp (>= 0.6.0)","rdoc (>= 4.0.0)","reline (>= 0.4.2)","prettyprint (>= 0)","erb (>= 0)","psych (>= 4.0.0)","date (>= 0)","stringio (>= 0)","io-console (~> 0.5)"]},{"name":"rubocop-rails","total_dependencies":28,"first_level_dependencies":5,"top_level_dependencies":{},"transitive_dependencies":["activesupport (>= 4.2.0)","lint_roller (~> 1.1)","rack (>= 1.1)","rubocop (>= 1.75.0, < 2.0)","rubocop-ast (>= 1.38.0, < 2.0)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","json (~> 2.3)","language_server-protocol (~> 3.17.0.2)","parallel (~> 1.10)","parser (>= 3.3.0.2)","rainbow (>= 2.2.2, < 4.0)","regexp_parser (>= 2.9.3, < 3.0)","ruby-progressbar (~> 1.7)","unicode-display_width (>= 2.4.0, < 4.0)","ast (~> 2.4.1)","racc (>= 0)","prism (~> 1.4)","unicode-emoji (~> 4.0, >= 4.0.4)"]},{"name":"rubocop-performance","total_dependencies":15,"first_level_dependencies":3,"top_level_dependencies":{},"transitive_dependencies":["lint_roller (~> 1.1)","rubocop (>= 1.75.0, < 2.0)","rubocop-ast (>= 1.38.0, < 2.0)","json (~> 2.3)","language_server-protocol (~> 3.17.0.2)","parallel (~> 1.10)","parser (>= 3.3.0.2)","rainbow (>= 2.2.2, < 4.0)","regexp_parser (>= 2.9.3, < 3.0)","ruby-progressbar (~> 1.7)","unicode-display_width (>= 2.4.0, < 4.0)","ast (~> 2.4.1)","racc (>= 0)","prism (~> 1.4)","unicode-emoji (~> 4.0, >= 4.0.4)"]},{"name":"html-pipeline","total_dependencies":14,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["activesupport (>= 2)","nokogiri (>= 1.4)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","racc (~> 1.4)"]},{"name":"rails-dom-testing","total_dependencies":14,"first_level_dependencies":3,"top_level_dependencies":{"actioncable":"actioncable (7.2.2.1)","actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","actionpack":"actionpack (7.2.2.1)","actionpack-xml_parser":"actionpack-xml_parser (2.0.1)","actiontext":"actiontext (7.2.2.1)","actionview":"actionview (7.2.2.1)","activestorage":"activestorage (7.2.2.1)","importmap-rails":"importmap-rails (2.1.0)","propshaft":"propshaft (1.1.0)","rails":"rails (7.2.2.1)","railties":"railties (7.2.2.1)","roadie-rails":"roadie-rails (3.3.0)","stimulus-rails":"stimulus-rails (1.3.4)"},"transitive_dependencies":["activesupport (>= 5.0.0)","minitest (>= 0)","nokogiri (>= 1.6)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)","racc (~> 1.4)"]},{"name":"rubocop","total_dependencies":14,"first_level_dependencies":10,"top_level_dependencies":{"rubocop-performance":"rubocop-performance (1.25.0)","rubocop-rails":"rubocop-rails (2.31.0)"},"transitive_dependencies":["json (~> 2.3)","language_server-protocol (~> 3.17.0.2)","lint_roller (~> 1.1.0)","parallel (~> 1.10)","parser (>= 3.3.0.2)","rainbow (>= 2.2.2, < 4.0)","regexp_parser (>= 2.9.3, < 3.0)","rubocop-ast (>= 1.44.0, < 2.0)","ruby-progressbar (~> 1.7)","unicode-display_width (>= 2.4.0, < 4.0)","ast (~> 2.4.1)","racc (>= 0)","prism (~> 1.4)","unicode-emoji (~> 4.0, >= 4.0.4)"]},{"name":"bullet","total_dependencies":13,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["activesupport (>= 3.0.0)","uniform_notifier (~> 1.11)","base64 (>= 0)","benchmark (>= 0.3)","bigdecimal (>= 0)","concurrent-ruby (~> 1.0, >= 1.3.1)","connection_pool (>= 2.2.5)","drb (>= 0)","i18n (>= 1.6, < 2)","logger (>= 1.4.2)","minitest (>= 5.1)","securerandom (>= 0.3)","tzinfo (~> 2.0, >= 2.0.5)"]},{"name":"capybara","total_dependencies":10,"first_level_dependencies":8,"top_level_dependencies":{},"transitive_dependencies":["addressable (>= 0)","matrix (>= 0)","mini_mime (>= 0.1.3)","nokogiri (~> 1.11)","rack (>= 1.6.0)","rack-test (>= 0.6.3)","regexp_parser (>= 1.5, < 3.0)","xpath (~> 3.2)","public_suffix (>= 2.0.2, < 7.0)","racc (~> 1.4)"]},{"name":"debug","total_dependencies":10,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["irb (~> 1.10)","reline (>= 0.3.8)","pp (>= 0.6.0)","rdoc (>= 4.0.0)","prettyprint (>= 0)","erb (>= 0)","psych (>= 4.0.0)","date (>= 0)","stringio (>= 0)","io-console (~> 0.5)"]},{"name":"mail","total_dependencies":7,"first_level_dependencies":4,"top_level_dependencies":{"actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","rails":"rails (7.2.2.1)"},"transitive_dependencies":["mini_mime (>= 0.1.1)","net-imap (>= 0)","net-pop (>= 0)","net-smtp (>= 0)","date (>= 0)","net-protocol (>= 0)","timeout (>= 0)"]},{"name":"selenium-webdriver","total_dependencies":5,"first_level_dependencies":5,"top_level_dependencies":{},"transitive_dependencies":["base64 (~> 0.2)","logger (~> 1.4)","rexml (~> 3.2, >= 3.2.5)","rubyzip (>= 1.2.2, < 3.0)","websocket (~> 1.0)"]},{"name":"rails_stats","total_dependencies":4,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["bundler-stats (>= 2.1)","rake (>= 0)","bundler (>= 1.9, < 3)","thor (>= 0.19.0, < 2.0)"]},{"name":"svg_sprite","total_dependencies":4,"first_level_dependencies":3,"top_level_dependencies":{},"transitive_dependencies":["nokogiri (>= 0)","svg_optimizer (>= 0)","thor (>= 0)","racc (~> 1.4)"]},{"name":"bundle-audit","total_dependencies":3,"first_level_dependencies":1,"top_level_dependencies":{},"transitive_dependencies":["bundler-audit (>= 0)","bundler (>= 1.2.0, < 3)","thor (~> 1.0)"]},{"name":"listen","total_dependencies":3,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["rb-fsevent (~> 0.10, >= 0.10.3)","rb-inotify (~> 0.9, >= 0.9.10)","ffi (~> 1.0)"]},{"name":"net-imap","total_dependencies":3,"first_level_dependencies":2,"top_level_dependencies":{"actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","mail":"mail (2.8.1)","rails":"rails (7.2.2.1)"},"transitive_dependencies":["date (>= 0)","net-protocol (>= 0)","timeout (>= 0)"]},{"name":"sanitize","total_dependencies":3,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["crass (~> 1.0.2)","nokogiri (>= 1.12.0)","racc (~> 1.4)"]},{"name":"simplecov","total_dependencies":3,"first_level_dependencies":3,"top_level_dependencies":{},"transitive_dependencies":["docile (~> 1.1)","simplecov-html (~> 0.11)","simplecov_json_formatter (~> 0.1)"]},{"name":"mini_magick","total_dependencies":2,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["benchmark (>= 0)","logger (>= 0)"]},{"name":"net-pop","total_dependencies":2,"first_level_dependencies":1,"top_level_dependencies":{"actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","mail":"mail (2.8.1)","rails":"rails (7.2.2.1)"},"transitive_dependencies":["net-protocol (>= 0)","timeout (>= 0)"]},{"name":"net-smtp","total_dependencies":2,"first_level_dependencies":1,"top_level_dependencies":{"actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","mail":"mail (2.8.1)","rails":"rails (7.2.2.1)"},"transitive_dependencies":["net-protocol (>= 0)","timeout (>= 0)"]},{"name":"rbpdf","total_dependencies":2,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["htmlentities (>= 0)","rbpdf-font (~> 1.19.0)"]},{"name":"rqrcode","total_dependencies":2,"first_level_dependencies":2,"top_level_dependencies":{},"transitive_dependencies":["chunky_png (~> 1.0)","rqrcode_core (~> 2.0)"]},{"name":"addressable","total_dependencies":1,"first_level_dependencies":1,"top_level_dependencies":{"capybara":"capybara (3.40.0)","css_parser":"css_parser (1.21.1)","roadie":"roadie (5.2.1)","roadie-rails":"roadie-rails (3.3.0)"},"transitive_dependencies":["public_suffix (>= 2.0.2, < 7.0)"]},{"name":"i18n","total_dependencies":1,"first_level_dependencies":1,"top_level_dependencies":{"actioncable":"actioncable (7.2.2.1)","actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","actionpack":"actionpack (7.2.2.1)","actionpack-xml_parser":"actionpack-xml_parser (2.0.1)","actiontext":"actiontext (7.2.2.1)","actionview":"actionview (7.2.2.1)","activejob":"activejob (7.2.2.1)","activemodel":"activemodel (7.2.2.1)","activerecord":"activerecord (7.2.2.1)","activestorage":"activestorage (7.2.2.1)","activesupport":"activesupport (7.2.2.1)","bullet":"bullet (8.0.7)","globalid":"globalid (1.2.1)","html-pipeline":"html-pipeline (2.13.2)","importmap-rails":"importmap-rails (2.1.0)","propshaft":"propshaft (1.1.0)","rails":"rails (7.2.2.1)","rails-dom-testing":"rails-dom-testing (2.2.0)","railties":"railties (7.2.2.1)","roadie-rails":"roadie-rails (3.3.0)","rubocop-rails":"rubocop-rails (2.31.0)","stimulus-rails":"stimulus-rails (1.3.4)"},"transitive_dependencies":["concurrent-ruby (~> 1.0)"]},{"name":"mocha","total_dependencies":1,"first_level_dependencies":1,"top_level_dependencies":{},"transitive_dependencies":["ruby2_keywords (>= 0.0.5)"]},{"name":"nokogiri","total_dependencies":1,"first_level_dependencies":1,"top_level_dependencies":{"actioncable":"actioncable (7.2.2.1)","actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","actionpack":"actionpack (7.2.2.1)","actionpack-xml_parser":"actionpack-xml_parser (2.0.1)","actiontext":"actiontext (7.2.2.1)","actionview":"actionview (7.2.2.1)","activestorage":"activestorage (7.2.2.1)","capybara":"capybara (3.40.0)","html-pipeline":"html-pipeline (2.13.2)","importmap-rails":"importmap-rails (2.1.0)","loofah":"loofah (2.24.1)","propshaft":"propshaft (1.1.0)","rails":"rails (7.2.2.1)","rails-dom-testing":"rails-dom-testing (2.2.0)","rails-html-sanitizer":"rails-html-sanitizer (1.6.2)","railties":"railties (7.2.2.1)","roadie":"roadie (5.2.1)","roadie-rails":"roadie-rails (3.3.0)","sanitize":"sanitize (6.1.3)","stimulus-rails":"stimulus-rails (1.3.4)","svg_optimizer":"svg_optimizer (0.3.0)","svg_sprite":"svg_sprite (1.0.3)","xpath":"xpath (3.2.0)"},"transitive_dependencies":["racc (~> 1.4)"]},{"name":"puma","total_dependencies":1,"first_level_dependencies":1,"top_level_dependencies":{},"transitive_dependencies":["nio4r (~> 2.0)"]},{"name":"commonmarker","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{},"transitive_dependencies":[]},{"name":"csv","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{},"transitive_dependencies":[]},{"name":"ffi","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{"listen":"listen (3.9.0)","rb-inotify":"rb-inotify (0.11.1)"},"transitive_dependencies":[]},{"name":"marcel","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{"actionmailbox":"actionmailbox (7.2.2.1)","actiontext":"actiontext (7.2.2.1)","activestorage":"activestorage (7.2.2.1)","rails":"rails (7.2.2.1)"},"transitive_dependencies":[]},{"name":"mini_mime","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{"actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","capybara":"capybara (3.40.0)","mail":"mail (2.8.1)","rails":"rails (7.2.2.1)"},"transitive_dependencies":[]},{"name":"net-ldap","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{},"transitive_dependencies":[]},{"name":"rack","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{"actioncable":"actioncable (7.2.2.1)","actionmailbox":"actionmailbox (7.2.2.1)","actionmailer":"actionmailer (7.2.2.1)","actionpack":"actionpack (7.2.2.1)","actionpack-xml_parser":"actionpack-xml_parser (2.0.1)","actiontext":"actiontext (7.2.2.1)","activestorage":"activestorage (7.2.2.1)","capybara":"capybara (3.40.0)","importmap-rails":"importmap-rails (2.1.0)","propshaft":"propshaft (1.1.0)","rack-session":"rack-session (2.1.1)","rack-test":"rack-test (2.2.0)","rackup":"rackup (2.2.1)","rails":"rails (7.2.2.1)","railties":"railties (7.2.2.1)","roadie-rails":"roadie-rails (3.3.0)","rubocop-rails":"rubocop-rails (2.31.0)","stimulus-rails":"stimulus-rails (1.3.4)"},"transitive_dependencies":[]},{"name":"rotp","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{},"transitive_dependencies":[]},{"name":"rouge","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{},"transitive_dependencies":[]},{"name":"rubyzip","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{"selenium-webdriver":"selenium-webdriver (4.32.0)"},"transitive_dependencies":[]},{"name":"tzinfo-data","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{},"transitive_dependencies":[]},{"name":"yard","total_dependencies":0,"first_level_dependencies":0,"top_level_dependencies":{},"transitive_dependencies":[]}]},{"name":"Models","files":"88","lines":"20110","loc":"14528","classes":"110","methods":"1532","m_over_c":"13","loc_over_m":"7"},{"name":"Validators","files":"1","lines":"29","loc":"10","classes":"1","methods":"1","m_over_c":"1","loc_over_m":"8"},{"name":"Javascripts","files":"117","lines":"6930","loc":"5362","classes":"0","methods":"446","m_over_c":"0","loc_over_m":"10"},{"name":"Jobs","files":"3","lines":"115","loc":"90","classes":"3","methods":"9","m_over_c":"3","loc_over_m":"8"},{"name":"Controllers","files":"57","lines":"9042","loc":"6746","classes":"60","methods":"554","m_over_c":"9","loc_over_m":"10"},{"name":"Helpers","files":"49","lines":"7068","loc":"5168","classes":"1","methods":"413","m_over_c":"413","loc_over_m":"10"},{"name":"Libraries","files":"134","lines":"18922","loc":"13178","classes":"128","methods":"1167","m_over_c":"9","loc_over_m":"9"},{"name":"Configuration","files":"17","lines":"1090","loc":"666","classes":"7","methods":"14","m_over_c":"2","loc_over_m":"45"},{"name":"Integration Tests","files":"98","lines":"10349","loc":"7237","classes":"104","methods":"297","m_over_c":"2","loc_over_m":"22"},{"name":"Test Support","files":"16","lines":"1637","loc":"1229","classes":"20","methods":"142","m_over_c":"7","loc_over_m":"6"},{"name":"Other Tests","files":"19","lines":"2339","loc":"1525","classes":"19","methods":"98","m_over_c":"5","loc_over_m":"13"},{"name":"Functional Tests","files":"65","lines":"35754","loc":"30234","classes":"65","methods":"2104","m_over_c":"32","loc_over_m":"12"},{"name":"Helper Tests","files":"27","lines":"5369","loc":"4090","classes":"28","methods":"302","m_over_c":"10","loc_over_m":"11"},{"name":"Unit Tests","files":"147","lines":"37173","loc":"28642","classes":"161","methods":"2778","m_over_c":"17","loc_over_m":"8"},{"name":"Job Tests","files":"2","lines":"142","loc":"94","classes":"2","methods":"2","m_over_c":"1","loc_over_m":"45"},{"name":"Code","files":"466","lines":"63306","loc":"45748","classes":"310","methods":"4136","m_over_c":"13","loc_over_m":"9","code_to_test_ratio":"1.6","total":true},{"name":"Tests","files":"374","lines":"92763","loc":"73051","classes":"399","methods":"5723","m_over_c":"14","loc_over_m":"10","code_to_test_ratio":"1.6","total":true},{"name":"Total","files":"840","lines":"156069","loc":"118799","classes":"709","methods":"9859","m_over_c":"13","loc_over_m":"10","code_to_test_ratio":"1.6","total":true}] ``` ### Testing @@ -287,15 +202,15 @@ Directory: /Users/etagwerker/Projects/fastruby/rails_stats/test/dummy In order to run the tests for this gem: ```bash -bundle exec rake +bundle exec rake test # Running: -. +.. -Fabulous run in 0.013349s, 74.9120 runs/s, 74.9120 assertions/s. +Fabulous run in 0.097903s, 20.4284 runs/s, 142.9987 assertions/s. -1 runs, 1 assertions, 0 failures, 0 errors, 0 skips +2 runs, 14 assertions, 0 failures, 0 errors, 0 skips ``` ### TODO diff --git a/lib/rails_stats/json_formatter.rb b/lib/rails_stats/json_formatter.rb index 4590464..a0ad8b0 100644 --- a/lib/rails_stats/json_formatter.rb +++ b/lib/rails_stats/json_formatter.rb @@ -3,17 +3,25 @@ module RailsStats class JSONFormatter < StatsFormatter def result - @result = @statistics.map { |key, stats| stat_hash(key, stats) } + @result = [] + old_stdout = $stdout + $stdout = StringIO.new + Bundler::Stats::CLI.start(["-f", "json"]) + bundler_stats_cli_json_result = $stdout.string + $stdout = old_stdout - if @grand_total - @result << stat_hash("Total", @grand_total).merge(code_test_hash) - end + @result << JSON.parse(bundler_stats_cli_json_result) unless bundler_stats_cli_json_result.strip.empty? + + @result += @statistics.map { |key, stats| stat_hash(key, stats) } + @result << stat_hash("Code", @code_total).merge(code_test_hash) if @code_total + @result << stat_hash("Tests", @tests_total).merge(code_test_hash) if @tests_total + @result << stat_hash("Total", @grand_total).merge(code_test_hash) if @grand_total @result end def to_s - puts result.to_json + puts JSON.generate(result, ascii_only: false) end private diff --git a/test/fixtures/console-output.txt b/test/fixtures/console-output.txt index 844985b..5069d28 100644 --- a/test/fixtures/console-output.txt +++ b/test/fixtures/console-output.txt @@ -1,8 +1,8 @@ +-----------------------|------------|----------------+ | Name | Total Deps | 1st Level Deps | +-----------------------|------------|----------------+ -| simplecov-console | 7 | 3 | -| codecov | 5 | 2 | +| simplecov-console | 8 | 3 | +| codecov | 4 | 1 | | rails_stats | 4 | 2 | | simplecov | 3 | 3 | | minitest-around | 1 | 1 | @@ -14,14 +14,14 @@ Declared Gems 9 Total Gems 18 - Unpinned Versions 8 + Unpinned Versions 6 Github Refs 0 +----------------------+---------+---------+---------+---------+---------+-----+-------+ | Name | Files | Lines | LOC | Classes | Methods | M/C | LOC/M | +----------------------+---------+---------+---------+---------+---------+-----+-------+ | Channels | 2 | 8 | 8 | 2 | 0 | 0 | 0 | -| Configuration | 19 | 417 | 111 | 1 | 0 | 0 | 0 | +| Configuration | 19 | 417 | 111 | 1 | 0 | 0 | 0 | | Controllers | 1 | 7 | 6 | 1 | 1 | 1 | 4 | | Helpers | 1 | 3 | 3 | 0 | 0 | 0 | 0 | | Javascripts | 3 | 27 | 7 | 0 | 0 | 0 | 0 | diff --git a/test/lib/rails_stats/json_formatter_test.rb b/test/lib/rails_stats/json_formatter_test.rb index b4b65bf..f47e228 100644 --- a/test/lib/rails_stats/json_formatter_test.rb +++ b/test/lib/rails_stats/json_formatter_test.rb @@ -5,126 +5,253 @@ describe RailsStats::JSONFormatter do describe "#result" do JSON_STRING = <<~EOS - [{ - "name": "Libraries", - "files": "1", - "lines": "1", - "loc": "1", - "classes": "0", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Mailers", - "files": "1", - "lines": "4", - "loc": "4", - "classes": "1", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Model Tests", - "files": "2", - "lines": "5", - "loc": "4", - "classes": "2", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Models", - "files": "1", - "lines": "3", - "loc": "3", - "classes": "1", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Javascripts", - "files": "3", - "lines": "27", - "loc": "7", - "classes": "0", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Jobs", - "files": "1", - "lines": "7", - "loc": "2", - "classes": "1", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Controllers", - "files": "1", - "lines": "7", - "loc": "6", - "classes": "1", - "methods": "1", - "m_over_c": "1", - "loc_over_m": "4" - }, { - "name": "Helpers", - "files": "1", - "lines": "3", - "loc": "3", - "classes": "0", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Channels", - "files": "2", - "lines": "8", - "loc": "8", - "classes": "2", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Configuration", - "files": "19", - "lines": "417", - "loc": "111", - "classes": "1", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Spec Support", - "files": "1", - "lines": "1", - "loc": "1", - "classes": "0", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Test Support", - "files": "1", - "lines": "1", - "loc": "1", - "classes": "0", - "methods": "0", - "m_over_c": "0", - "loc_over_m": "0" - }, { - "name": "Total", - "files": "34", - "lines": "484", - "loc": "151", - "classes": "9", - "methods": "1", - "m_over_c": "0", - "loc_over_m": "149", - "code_to_test_ratio": "0.0", - "total": true - }] + [{ + "summary": { + "declared": 9, + "unpinned": 6, + "total": 18, + "github": 0 + }, + "gems": [ + { + "name": "simplecov-console", + "total_dependencies": 8, + "first_level_dependencies": 3, + "top_level_dependencies": {}, + "transitive_dependencies": [ + "ansi (>= 0)", + "simplecov (>= 0)", + "terminal-table (>= 0)", + "docile (~> 1.1)", + "simplecov-html (~> 0.11)", + "simplecov_json_formatter (~> 0.1)", + "unicode-display_width (>= 1.1.1, < 4)", + "unicode-emoji (~> 4.0, >= 4.0.4)" + ] + }, + { + "name": "codecov", + "total_dependencies": 4, + "first_level_dependencies": 1, + "top_level_dependencies": {}, + "transitive_dependencies": [ + "simplecov (>= 0.15, < 0.22)", + "docile (~> 1.1)", + "simplecov-html (~> 0.11)", + "simplecov_json_formatter (~> 0.1)" + ] + }, + { + "name": "rails_stats", + "total_dependencies": 4, + "first_level_dependencies": 2, + "top_level_dependencies": {}, + "transitive_dependencies": [ + "bundler-stats (>= 2.1)", + "rake (>= 0)", + "bundler (>= 1.9, < 3)", + "thor (>= 0.19.0, < 2.0)" + ] + }, + { + "name": "simplecov", + "total_dependencies": 3, + "first_level_dependencies": 3, + "top_level_dependencies": { + "codecov": "codecov (0.6.0)", + "simplecov-console": "simplecov-console (0.9.3)" + }, + "transitive_dependencies": [ + "docile (~> 1.1)", + "simplecov-html (~> 0.11)", + "simplecov_json_formatter (~> 0.1)" + ] + }, + { + "name": "minitest-around", + "total_dependencies": 1, + "first_level_dependencies": 1, + "top_level_dependencies": {}, + "transitive_dependencies": [ + "minitest (~> 5.0)" + ] + }, + { + "name": "bundler", + "total_dependencies": 0, + "first_level_dependencies": 0, + "top_level_dependencies": { + "bundler-stats": "bundler-stats (2.4.0)", + "rails_stats": "rails_stats (2.0.1)" + }, + "transitive_dependencies": [] + }, + { + "name": "byebug", + "total_dependencies": 0, + "first_level_dependencies": 0, + "top_level_dependencies": {}, + "transitive_dependencies": [] + }, + { + "name": "minitest", + "total_dependencies": 0, + "first_level_dependencies": 0, + "top_level_dependencies": { + "minitest-around": "minitest-around (0.5.0)" + }, + "transitive_dependencies": [] + }, + { + "name": "minitest-spec-context", + "total_dependencies": 0, + "first_level_dependencies": 0, + "top_level_dependencies": {}, + "transitive_dependencies": [] + } + ] + },{ + "name": "Mailers", + "files": "1", + "lines": "4", + "loc": "4", + "classes": "1", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Helpers", + "files": "1", + "lines": "3", + "loc": "3", + "classes": "0", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Jobs", + "files": "1", + "lines": "7", + "loc": "2", + "classes": "1", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Controllers", + "files": "1", + "lines": "7", + "loc": "6", + "classes": "1", + "methods": "1", + "m_over_c": "1", + "loc_over_m": "4" + }, { + "name": "Models", + "files": "1", + "lines": "3", + "loc": "3", + "classes": "1", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Channels", + "files": "2", + "lines": "8", + "loc": "8", + "classes": "2", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Javascripts", + "files": "3", + "lines": "27", + "loc": "7", + "classes": "0", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Libraries", + "files": "1", + "lines": "1", + "loc": "1", + "classes": "0", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Configuration", + "files": "19", + "lines": "417", + "loc": "111", + "classes": "1", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Model Tests", + "files": "2", + "lines": "5", + "loc": "4", + "classes": "2", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Spec Support", + "files": "1", + "lines": "1", + "loc": "1", + "classes": "0", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Test Support", + "files": "1", + "lines": "1", + "loc": "1", + "classes": "0", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0" + }, { + "name": "Code", + "files": "30", + "lines": "477", + "loc": "145", + "classes": "7", + "methods": "1", + "m_over_c": "0", + "loc_over_m": "143", + "code_to_test_ratio": "0.0", + "total": true + }, { + "name": "Tests", + "files": "4", + "lines": "7", + "loc": "6", + "classes": "2", + "methods": "0", + "m_over_c": "0", + "loc_over_m": "0", + "code_to_test_ratio": "0.0", + "total": true + }, { + "name": "Total", + "files": "34", + "lines": "484", + "loc": "151", + "classes": "9", + "methods": "1", + "m_over_c": "0", + "loc_over_m": "149", + "code_to_test_ratio": "0.0", + "total": true + }] EOS it "outputs useful stats for a Rails project" do @@ -133,12 +260,28 @@ calculator = RailsStats::StatsCalculator.new(root_directory) formatter = RailsStats::JSONFormatter.new(calculator) - sorted_expectation = JSON.parse(JSON_STRING).sort {|x, y| x["name"] <=> y["name"] } - sorted_result = formatter.result.sort {|x, y| x["name"] <=> y["name"] } + expectation = JSON.parse(JSON_STRING) + result = formatter.result - sorted_expectation.each_with_index do |x, i| - assert_equal x, sorted_result[i] + [expectation, result].each do |data| + data.each do |hash| + next unless hash["gems"] + + hash["gems"].each do |gem| + next unless gem["transitive_dependencies"] + + gem["transitive_dependencies"].map! do |dep| + name, constraints = dep.split(/[()]/) + next dep unless constraints + + normalized_constraints = constraints.split(/,\s*/).sort.join(', ') + "#{name}(#{normalized_constraints})" + end.sort! + end + end end + + assert_equal expectation, result end end end \ No newline at end of file