diff --git a/CHANGELOG.md b/CHANGELOG.md index f9217bd..1a80f1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## main [(unreleased)](https://github.com/fastruby/skunk/compare/v0.5.4...HEAD) +* [FEATURE: Indicate `--out PATH` location](https://github.com/fastruby/skunk/pull/131) * [FEATURE: Add `--formats` CLI flag to select report formats (json, html, console)](https://github.com/fastruby/skunk/pull/130) * [REFACTOR: Move Console Report](https://github.com/fastruby/skunk/pull/128) * [BUGFIX: Set the right content type in the share HTTP request](https://github.com/fastruby/skunk/pull/129) diff --git a/README.md b/README.md index 1792f04..e16be5c 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Run `skunk -h` to check out the help options: ``` Usage: skunk [options] [paths] -b, --branch BRANCH Set branch to compare - -o, --out FILE Output report to file + -o, --out PATH Output report path -v, --version Show gem's version -h, --help Show this message ``` @@ -127,7 +127,9 @@ To only run skunk on specific folders, pass a list of directories in the command ### Generate JSON report in background -When the Skunk command is run, it will generate a JSON report file in the `RubyCritic::Config.root` location. +When the Skunk command is run, it will generate a JSON report file in the configured output path. + +Skunk also writes the console report to `skunk_report.txt` under the same output path. ### Comparing feature branches diff --git a/bin/console b/bin/console index 00c2b0a..623d374 100755 --- a/bin/console +++ b/bin/console @@ -13,5 +13,6 @@ puts ARGV.inspect require "skunk/cli/application" require "skunk/config" -Skunk::Config.formats = %i[json console html] +Skunk::Config.formats = %i[json console html] # supported output formats +Skunk::Config.root = "tmp/rubycritic" # default path to store generated JSON and HTML reports. Skunk::Cli::Application.new(ARGV).execute diff --git a/lib/skunk/cli/application.rb b/lib/skunk/cli/application.rb index f928098..3877dce 100644 --- a/lib/skunk/cli/application.rb +++ b/lib/skunk/cli/application.rb @@ -49,14 +49,8 @@ def warn_coverage_info warn "warning: Having no coverage metrics will make your SkunkScore worse." end - # :reek:NilCheck def print(message) - filename = @parsed_options[:output_filename] - if filename.nil? - $stdout.puts(message) - else - File.open(filename, "a") { |file| file << message } - end + $stdout.puts(message) end end end diff --git a/lib/skunk/cli/options/argv.rb b/lib/skunk/cli/options/argv.rb index 4141947..94c3309 100644 --- a/lib/skunk/cli/options/argv.rb +++ b/lib/skunk/cli/options/argv.rb @@ -10,9 +10,6 @@ class Options # Extends RubyCritic::Cli::Options::Argv to parse a subset of the # parameters accepted by RubyCritic class Argv < RubyCritic::Cli::Options::Argv - # :reek:Attribute - attr_accessor :output_filename - def parse parser.new do |opts| opts.banner = "Usage: skunk [options] [paths]\n" @@ -23,8 +20,8 @@ def parse self.mode = :compare_branches end - opts.on("-o", "--out FILE", "Output report to file") do |filename| - self.output_filename = filename + opts.on("-o", "--out PATH", "Output report path") do |path| + Skunk::Config.root = path end opts.on("-f", "--formats json,html,console", Array, "Output formats: json,html,console") do |list| @@ -40,10 +37,6 @@ def parse end end.parse!(@argv) end - - def to_h - super.merge(output_filename: output_filename) - end end end end diff --git a/lib/skunk/commands/status_sharer.rb b/lib/skunk/commands/status_sharer.rb index f46971a..653e21b 100644 --- a/lib/skunk/commands/status_sharer.rb +++ b/lib/skunk/commands/status_sharer.rb @@ -73,7 +73,11 @@ def share_enabled? # @return [Boolean] Check if share URL is empty def share_url_empty? - ENV["SHARE_URL"].to_s == "" + share_url == "" + end + + def share_url + ENV["SHARE_URL"].to_s end def payload diff --git a/lib/skunk/config.rb b/lib/skunk/config.rb index 769590d..aeec57b 100644 --- a/lib/skunk/config.rb +++ b/lib/skunk/config.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "rubycritic/configuration" + module Skunk # Utility module for format validation module FormatValidator @@ -28,10 +30,12 @@ class Configuration def initialize @formats = [DEFAULT_FORMAT] + @root = RubyCritic::Config.root end def set(options = {}) self.formats = options[:formats] if options.key?(:formats) + self.root = options[:root] if options.key?(:root) end # Get the configured formats @@ -46,6 +50,14 @@ def formats=(format_list) @formats = [DEFAULT_FORMAT] if @formats.empty? end + def root + @root || File.expand_path("tmp/rubycritic", Dir.pwd) + end + + def root=(path) + @root = path.nil? || path.to_s.empty? ? nil : File.expand_path(path.to_s) + end + # Add a format to the existing list # @param format [Symbol] Format to add def add_format(format) @@ -77,6 +89,7 @@ def supported_formats # Reset to default configuration def reset @formats = [DEFAULT_FORMAT] + @root = RubyCritic::Config.root end end diff --git a/lib/skunk/generators/console_report.rb b/lib/skunk/generators/console_report.rb index 3b1958e..774eae7 100644 --- a/lib/skunk/generators/console_report.rb +++ b/lib/skunk/generators/console_report.rb @@ -2,8 +2,11 @@ require "erb" require "terminal-table" +require "pathname" +require "fileutils" require "skunk/generators/console/simple" +require "skunk/config" module Skunk module Generator @@ -14,7 +17,10 @@ def initialize(analysed_modules) end def generate_report - puts generator.render + content = generator.render + puts content + FileUtils.mkdir_p(file_directory) + File.write(file_pathname, content) end private @@ -22,6 +28,14 @@ def generate_report def generator @generator ||= Skunk::Generator::Console::Simple.new(@analysed_modules) end + + def file_directory + @file_directory ||= Pathname.new(Skunk::Config.root) + end + + def file_pathname + Pathname.new(file_directory).join("skunk_report.txt") + end end end end diff --git a/lib/skunk/generators/html/overview.rb b/lib/skunk/generators/html/overview.rb index 78e7d2b..fec1033 100644 --- a/lib/skunk/generators/html/overview.rb +++ b/lib/skunk/generators/html/overview.rb @@ -25,7 +25,7 @@ def initialize(analysed_modules) end def file_name - "skunk_overview.html" + "skunk_report.html" end def render @@ -49,6 +49,10 @@ def files FileData.new(module_data) end end + + def root_directory + @root_directory ||= Pathname.new(Skunk::Config.root) + end end end end diff --git a/lib/skunk/generators/json/simple.rb b/lib/skunk/generators/json/simple.rb index 0a686ce..353d767 100644 --- a/lib/skunk/generators/json/simple.rb +++ b/lib/skunk/generators/json/simple.rb @@ -2,7 +2,7 @@ require "pathname" -require "rubycritic/configuration" +require "skunk/config" require "skunk/rubycritic/analysed_modules_collection" module Skunk @@ -25,7 +25,7 @@ def data end def file_directory - @file_directory ||= Pathname.new(RubyCritic::Config.root) + @file_directory ||= Pathname.new(Skunk::Config.root) end def file_pathname diff --git a/test/lib/skunk/application_test.rb b/test/lib/skunk/application_test.rb index 8055646..5e2cc3f 100644 --- a/test/lib/skunk/application_test.rb +++ b/test/lib/skunk/application_test.rb @@ -2,6 +2,7 @@ require "test_helper" require "skunk/cli/application" +require "skunk/commands/default" require "rubycritic/core/analysed_module" require "minitest/stub_const" @@ -46,14 +47,15 @@ end context "when passing an environment variable SHARE=true" do - let(:argv) { ["--out=tmp/shared_report.txt", "samples/rubycritic"] } + let(:argv) { ["--out=tmp", "samples/rubycritic"] } let(:success_code) { 0 } - let(:shared_message) do - "Shared at: https://skunk.fastruby.io/j" - end + let(:generated_message) { "Generated with Skunk" } + let(:shared_message) { "Shared at: https://skunk.fastruby.io/j" } + let(:share_url) { "https://skunk.fastruby.io" } + let(:report_path) { "tmp/skunk_report.txt" } around do |example| - stub_request(:post, "https://skunk.fastruby.io/reports").to_return( + stub_request(:post, "#{share_url}/reports").to_return( status: 200, body: '{"id":"j"}', headers: { "Content-Type" => "application/json" } @@ -62,20 +64,21 @@ end it "share report to default server" do - FileUtils.rm("tmp/shared_report.txt", force: true) + FileUtils.rm(report_path, force: true) FileUtils.mkdir_p("tmp") - RubyCritic::AnalysedModule.stub_any_instance(:churn, 1) do - RubyCritic::AnalysedModule.stub_any_instance(:coverage, 100.0) do - Skunk::Command::Default.stub_any_instance(:share_enabled?, true) do - Skunk::Command::StatusSharer.stub_any_instance(:not_sharing?, false) do - Skunk::Command::StatusSharer.stub_any_instance(:share, "Shared at: https://skunk.fastruby.io/j") do - result = application.execute - _(result).must_equal success_code - output = File.read("tmp/shared_report.txt") - _(output).must_include(shared_message) - end + Skunk::Command::Default.stub_any_instance(:share_enabled?, true) do + Skunk::Command::StatusSharer.stub_any_instance(:share_url, share_url) do + Skunk::Command::StatusSharer.stub_any_instance(:share, "Shared at: #{share_url}/j") do + stdout = capture_stdout do + result = application.execute + _(result).must_equal success_code end + _(File.exist?(report_path)).must_equal true + file_output = File.read(report_path) + + _(file_output).must_include(generated_message) + _(stdout).must_include(shared_message) end end end diff --git a/test/lib/skunk/cli/options/argv_test.rb b/test/lib/skunk/cli/options/argv_test.rb index bffe1bd..613ef42 100644 --- a/test/lib/skunk/cli/options/argv_test.rb +++ b/test/lib/skunk/cli/options/argv_test.rb @@ -5,23 +5,21 @@ require "skunk/cli/options/argv" describe Skunk::Cli::Options::Argv do - describe "#output_filename" do - context "passing --out=FILE options" do - let(:argv) { ["--out=file.txt"] } + describe "--out path" do + after do + Skunk::Config.reset + end - it "parses passed filename" do - parser = Skunk::Cli::Options::Argv.new(argv) - parser.parse - _(parser.output_filename).must_equal "file.txt" - end + it "sets Skunk::Config.root to the provided path" do + parser = Skunk::Cli::Options::Argv.new(["--out=tmp/custom"]) + parser.parse + _(Skunk::Config.root).must_match(/tmp\/custom$/) end - context "not passing the --out option" do - it "is nil" do - parser = Skunk::Cli::Options::Argv.new([]) - parser.parse - _(parser.output_filename).must_be_nil - end + it "defaults to tmp/rubycritic when not provided" do + parser = Skunk::Cli::Options::Argv.new([]) + parser.parse + _(Skunk::Config.root).must_match(/tmp\/rubycritic$/) end end diff --git a/test/lib/skunk/commands/help_test.rb b/test/lib/skunk/commands/help_test.rb index 9374e0f..6ff3d24 100644 --- a/test/lib/skunk/commands/help_test.rb +++ b/test/lib/skunk/commands/help_test.rb @@ -11,7 +11,7 @@ <<~HELP Usage: skunk [options] [paths] -b, --branch BRANCH Set branch to compare - -o, --out FILE Output report to file + -o, --out PATH Output report path -f, --formats json,html,console Output formats: json,html,console -v, --version Show gem's version -h, --help Show this message diff --git a/test/lib/skunk/config_test.rb b/test/lib/skunk/config_test.rb index a04e1c6..342cb34 100644 --- a/test/lib/skunk/config_test.rb +++ b/test/lib/skunk/config_test.rb @@ -79,5 +79,14 @@ def test_reset Config.reset assert_equal [:console], Config.formats end + + def test_default_root + assert_match(/tmp\/rubycritic$/, Config.root) + end + + def test_set_root_expands_path + Config.root = "tmp/custom" + assert_equal File.expand_path("tmp/custom", Dir.pwd), Config.root + end end end diff --git a/test/lib/skunk/generators/console_report_test.rb b/test/lib/skunk/generators/console_report_test.rb index 6f880de..c63e9d5 100644 --- a/test/lib/skunk/generators/console_report_test.rb +++ b/test/lib/skunk/generators/console_report_test.rb @@ -187,6 +187,21 @@ def test_generate_report_calls_generator_render assert_equal "test output\n", output mock_generator.verify end + + def test_generate_report_writes_console_file + Skunk::Config.root = "tmp/console_report" + begin + path = File.join(Skunk::Config.root, "skunk_report.txt") + File.delete(path) if File.exist?(path) + + @console_report.generate_report + + assert File.exist?(path) + assert_includes File.read(path), "SkunkScore Total" + ensure + FileUtils.rm_rf(Skunk::Config.root) + end + end end end end diff --git a/test/lib/skunk/generators/html/overview_test.rb b/test/lib/skunk/generators/html/overview_test.rb new file mode 100644 index 0000000..5f5d018 --- /dev/null +++ b/test/lib/skunk/generators/html/overview_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "minitest/autorun" +require "skunk/generators/html/overview" +require "skunk/config" + +module Skunk + module Generator + module Html + class OverviewTest < Minitest::Test + def teardown + Skunk::Config.reset + end + + def test_root_directory_uses_skunk_config_root + Skunk::Config.root = "tmp/custom_html" + analysed_modules = Minitest::Mock.new + generator = Overview.new(analysed_modules) + + root = generator.send(:root_directory) + assert_equal File.expand_path("tmp/custom_html", Dir.pwd), root.to_s + end + end + end + end +end \ No newline at end of file