Drop 2.3 ruby support (#108)

This commit is contained in:
Ivan Shamatov 2021-02-03 11:43:17 +03:00 committed by GitHub
parent 080d225576
commit 5cbcddd3c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 962 additions and 998 deletions

View File

@ -15,7 +15,7 @@ name: ci
pull_request: pull_request:
branches: branches:
- master - master
create: create:
jobs: jobs:
tests: tests:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -7,5 +7,4 @@ jobs:
- "2.6" - "2.6"
- "2.5" - "2.5"
- "2.4" - "2.4"
- "2.3"
- "jruby" - "jruby"

View File

@ -8,8 +8,7 @@ group :test do
gem "simplecov", require: false, platforms: :ruby gem "simplecov", require: false, platforms: :ruby
gem "simplecov-cobertura", require: false, platforms: :ruby gem "simplecov-cobertura", require: false, platforms: :ruby
gem "rexml", require: false gem "rexml", require: false
gem "warning"
gem "warning" if RUBY_VERSION >= "2.4.0"
end end
group :tools do group :tools do

View File

@ -1,8 +1,8 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# frozen_string_literal: true # frozen_string_literal: true
require 'bundler/setup' require "bundler/setup"
require 'dry/cli' require "dry/cli"
# You can add fixtures and/or initialization code here to make experimenting # You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like. # with your gem easier. You can also use a different console, if you like.
@ -11,5 +11,5 @@ require 'dry/cli'
# require "pry" # require "pry"
# Pry.start # Pry.start
require 'irb' require "irb"
IRB.start(__FILE__) IRB.start(__FILE__)

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'dry/cli/program_name' require "dry/cli/program_name"
module Dry module Dry
class CLI class CLI
@ -49,7 +49,7 @@ module Dry
def self.command_examples(command, name) def self.command_examples(command, name)
return if command.examples.empty? return if command.examples.empty?
"\nExamples:\n#{command.examples.map { |example| " #{name} #{example}" }.join("\n")}" # rubocop:disable Metrics/LineLength "\nExamples:\n#{command.examples.map { |example| " #{name} #{example}" }.join("\n")}"
end end
# @since 0.1.0 # @since 0.1.0
@ -86,18 +86,18 @@ module Dry
required_arguments = command.required_arguments required_arguments = command.required_arguments
optional_arguments = command.optional_arguments optional_arguments = command.optional_arguments
required = required_arguments.map { |arg| arg.name.upcase }.join(' ') if required_arguments.any? # rubocop:disable Metrics/LineLength required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any? # rubocop:disable Metrics/LineLength
optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(' ') if optional_arguments.any? # rubocop:disable Metrics/LineLength optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any? # rubocop:disable Metrics/LineLength
result = [required, optional].compact result = [required, optional].compact
" #{result.join(' ')}" unless result.empty? " #{result.join(" ")}" unless result.empty?
end end
# @since 0.1.0 # @since 0.1.0
# @api private # @api private
def self.extended_command_arguments(command) def self.extended_command_arguments(command)
command.arguments.map do |argument| command.arguments.map do |argument|
" #{argument.name.to_s.upcase.ljust(32)} # #{'REQUIRED ' if argument.required?}#{argument.desc}" # rubocop:disable Metrics/LineLength " #{argument.name.to_s.upcase.ljust(32)} # #{"REQUIRED " if argument.required?}#{argument.desc}" # rubocop:disable Metrics/LineLength
end.join("\n") end.join("\n")
end end
@ -114,14 +114,14 @@ module Dry
else else
"#{name}=VALUE" "#{name}=VALUE"
end end
name = "#{name}, #{option.alias_names.join(', ')}" if option.aliases.any? name = "#{name}, #{option.alias_names.join(", ")}" if option.aliases.any?
name = " --#{name.ljust(30)}" name = " --#{name.ljust(30)}"
name = "#{name} # #{option.desc}" name = "#{name} # #{option.desc}"
name = "#{name}, default: #{option.default.inspect}" unless option.default.nil? name = "#{name}, default: #{option.default.inspect}" unless option.default.nil?
name name
end end
result << " --#{'help, -h'.ljust(30)} # Print this help" result << " --#{"help, -h".ljust(30)} # Print this help"
result.join("\n") result.join("\n")
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'forwardable' require "forwardable"
require 'dry/cli/option' require "dry/cli/option"
module Dry module Dry
class CLI class CLI
@ -369,7 +369,7 @@ module Dry
required_arguments required_arguments
optional_arguments optional_arguments
subcommands subcommands
] => 'self.class' ] => "self.class"
end end
end end
end end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'set' require "set"
module Dry module Dry
class CLI class CLI

View File

@ -10,7 +10,7 @@ module Dry
def self.dasherize(input) def self.dasherize(input)
return nil unless input return nil unless input
input.to_s.downcase.gsub(/[[[:space:]]_]/, '-') input.to_s.downcase.gsub(/[[[:space:]]_]/, "-")
end end
end end
end end

View File

@ -1,10 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'backports/2.5.0/module/define_method' if RUBY_VERSION < '2.5' require "backports/2.5.0/module/define_method" if RUBY_VERSION < "2.5"
module Dry module Dry
class CLI class CLI
require 'dry/cli' require "dry/cli"
# Inline Syntax (aka DSL) to implement one-file applications # Inline Syntax (aka DSL) to implement one-file applications
# #
# `dry/cli/inline` is not required by default # `dry/cli/inline` is not required by default

View File

@ -32,7 +32,7 @@ module Dry
# @api private # @api private
def desc def desc
desc = options[:desc] desc = options[:desc]
values ? "#{desc}: (#{values.join('/')})" : desc values ? "#{desc}: (#{values.join("/")})" : desc
end end
# @since 0.1.0 # @since 0.1.0
@ -108,7 +108,7 @@ module Dry
# @api private # @api private
def alias_names def alias_names
aliases aliases
.map { |name| name.gsub(/^-{1,2}/, '') } .map { |name| name.gsub(/^-{1,2}/, "") }
.compact .compact
.uniq .uniq
.map { |name| name.size == 1 ? "-#{name}" : "--#{name}" } .map { |name| name.size == 1 ? "-#{name}" : "--#{name}" }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'optparse' require "optparse"
require 'dry/cli/program_name' require "dry/cli/program_name"
module Dry module Dry
class CLI class CLI
@ -24,7 +24,7 @@ module Dry
end end
end end
opts.on_tail('-h', '--help') do opts.on_tail("-h", "--help") do
return Result.help return Result.help
end end
end.parse!(arguments) end.parse!(arguments)
@ -32,7 +32,7 @@ module Dry
parsed_options = command.default_params.merge(parsed_options) parsed_options = command.default_params.merge(parsed_options)
parse_required_params(command, arguments, prog_name, parsed_options) parse_required_params(command, arguments, prog_name, parsed_options)
rescue ::OptionParser::ParseError rescue ::OptionParser::ParseError
Result.failure("ERROR: \"#{prog_name}\" was called with arguments \"#{original_arguments.join(' ')}\"") # rubocop:disable Metrics/LineLength Result.failure("ERROR: \"#{prog_name}\" was called with arguments \"#{original_arguments.join(" ")}\"") # rubocop:disable Metrics/LineLength
end end
# @since 0.1.0 # @since 0.1.0
@ -49,14 +49,14 @@ module Dry
unless all_required_params_satisfied unless all_required_params_satisfied
parsed_required_params_values = parsed_required_params.values.compact parsed_required_params_values = parsed_required_params.values.compact
usage = "\nUsage: \"#{prog_name} #{command.required_arguments.map(&:description_name).join(' ')}" # rubocop:disable Metrics/LineLength usage = "\nUsage: \"#{prog_name} #{command.required_arguments.map(&:description_name).join(" ")}" # rubocop:disable Metrics/LineLength
usage += " | #{prog_name} SUBCOMMAND" if command.subcommands.any? usage += " | #{prog_name} SUBCOMMAND" if command.subcommands.any?
usage += '"' usage += '"'
if parsed_required_params_values.empty? if parsed_required_params_values.empty?
return Result.failure("ERROR: \"#{prog_name}\" was called with no arguments#{usage}") # rubocop:disable Metrics/LineLength return Result.failure("ERROR: \"#{prog_name}\" was called with no arguments#{usage}")
else else
return Result.failure("ERROR: \"#{prog_name}\" was called with arguments #{parsed_required_params_values}#{usage}") # rubocop:disable Metrics/LineLength return Result.failure("ERROR: \"#{prog_name}\" was called with arguments #{parsed_required_params_values}#{usage}") # rubocop:disable Metrics/LineLength
end end
@ -101,7 +101,7 @@ module Dry
# @since 0.1.0 # @since 0.1.0
# @api private # @api private
def self.failure(error = 'Error: Invalid param provided') def self.failure(error = "Error: Invalid param provided")
new(error: error) new(error: error)
end end

View File

@ -9,7 +9,7 @@ module Dry
module ProgramName module ProgramName
# @since 0.1.0 # @since 0.1.0
# @api private # @api private
SEPARATOR = ' ' SEPARATOR = " "
# @since 0.1.0 # @since 0.1.0
# @api private # @api private

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'dry/cli/command_registry' require "dry/cli/command_registry"
module Dry module Dry
class CLI class CLI
@ -272,7 +272,7 @@ module Dry
private private
COMMAND_NAME_SEPARATOR = ' ' COMMAND_NAME_SEPARATOR = " "
# @since 0.2.0 # @since 0.2.0
# @api private # @api private

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'dry/cli/program_name' require "dry/cli/program_name"
module Dry module Dry
class CLI class CLI
@ -11,13 +11,13 @@ module Dry
module Usage module Usage
# @since 0.1.0 # @since 0.1.0
# @api private # @api private
SUBCOMMAND_BANNER = ' [SUBCOMMAND]' SUBCOMMAND_BANNER = " [SUBCOMMAND]"
ROOT_COMMAND_WITH_SUBCOMMANDS_BANNER = ' [ARGUMENT|SUBCOMMAND]' ROOT_COMMAND_WITH_SUBCOMMANDS_BANNER = " [ARGUMENT|SUBCOMMAND]"
# @since 0.1.0 # @since 0.1.0
# @api private # @api private
def self.call(result) def self.call(result)
header = 'Commands:' header = "Commands:"
max_length, commands = commands_and_arguments(result) max_length, commands = commands_and_arguments(result)
commands.map do |banner, node| commands.map do |banner, node|
@ -55,11 +55,11 @@ module Dry
required_arguments = command.required_arguments required_arguments = command.required_arguments
optional_arguments = command.optional_arguments optional_arguments = command.optional_arguments
required = required_arguments.map { |arg| arg.name.upcase }.join(' ') if required_arguments.any? # rubocop:disable Metrics/LineLength required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any? # rubocop:disable Metrics/LineLength
optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(' ') if optional_arguments.any? # rubocop:disable Metrics/LineLength optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any? # rubocop:disable Metrics/LineLength
result = [required, optional].compact result = [required, optional].compact
" #{result.join(' ')}" unless result.empty? " #{result.join(" ")}" unless result.empty?
end end
# @since 0.1.0 # @since 0.1.0
@ -73,7 +73,7 @@ module Dry
# @since 0.1.0 # @since 0.1.0
# @api private # @api private
def self.justify(string, padding, usage) def self.justify(string, padding, usage)
return string.chomp(' ') if usage.nil? return string.chomp(" ") if usage.nil?
string.ljust(padding + padding / 2) string.ljust(padding + padding / 2)
end end

View File

@ -1,8 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'pathname' require "pathname"
require 'fileutils' require "fileutils"
require 'backports/2.4.0/string/match' if RUBY_VERSION < '2.4'
module Dry module Dry
class CLI class CLI
@ -33,7 +32,7 @@ module Dry
# @since 0.3.1 # @since 0.3.1
def self.write(path, *content) def self.write(path, *content)
mkdir_p(path) mkdir_p(path)
open(path, ::File::CREAT | ::File::WRONLY | ::File::TRUNC, *content) # rubocop:disable LineLength, Security/Open - this isn't a call to `::Kernel.open`, but to `self.open` open(path, ::File::CREAT | ::File::WRONLY | ::File::TRUNC, *content) # rubocop:disable Security/Open - this isn't a call to `::Kernel.open`, but to `self.open`
end end
# Copies source into destination. # Copies source into destination.
@ -315,7 +314,7 @@ module Dry
starting = index(content, path, target) starting = index(content, path, target)
line = content[starting] line = content[starting]
size = line[/\A[[:space:]]*/].bytesize size = line[/\A[[:space:]]*/].bytesize
closing = (' ' * size) + (target.match?(/{/) ? '}' : 'end') closing = (" " * size) + (target.match?(/{/) ? "}" : "end")
ending = starting + index(content[starting..-1], path, closing) ending = starting + index(content[starting..-1], path, closing)
content.slice!(starting..ending) content.slice!(starting..ending)

View File

@ -3,6 +3,6 @@
module Dry module Dry
class CLI class CLI
# @since 0.1.0 # @since 0.1.0
VERSION = '0.6.0' VERSION = "0.6.0"
end end
end end

View File

@ -4,10 +4,10 @@ gemspec:
authors: ["Luca Guidi"] authors: ["Luca Guidi"]
email: ["me@lucaguidi.com"] email: ["me@lucaguidi.com"]
summary: "Common framework to build command line interfaces with Ruby" summary: "Common framework to build command line interfaces with Ruby"
required_ruby_version: ">= 2.3.0" required_ruby_version: ">= 2.4.0"
development_dependencies: development_dependencies:
- [bundler, ">= 1.6", "< 3"] - [bundler, ">= 1.6", "< 3"]
- [rake, "~> 13.0"] - [rake, "~> 13.0"]
- [rspec, "~> 3.7"] - [rspec, "~> 3.7"]
- [simplecov, "~> 0.17.1"] - [simplecov, "~> 0.17.1"]
- [rubocop, "0.81"] - [rubocop, "~> 0.82"]

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe 'Commands' do RSpec.describe "Commands" do
context 'with extra params' do context "with extra params" do
context 'when there is a required argument' do context "when there is a required argument" do
context 'and there are options' do context "and there are options" do
it 'parses both separately' do it "parses both separately" do
output = `foo variadic with-mandatory-and-options uno -- due tre --blah` output = `foo variadic with-mandatory-and-options uno -- due tre --blah`
expect(output).to eq("first: uno\nurl: \nmethod: \nUnused Arguments: due, tre, --blah\n") # rubocop:disable Metrics/LineLength expect(output).to eq("first: uno\nurl: \nmethod: \nUnused Arguments: due, tre, --blah\n")
end end
end end
end end

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'open3' require "open3"
RSpec.describe 'Inline' do RSpec.describe "Inline" do
context 'with command' do context "with command" do
let(:cmd) { 'inline' } let(:cmd) { "inline" }
it 'shows help' do it "shows help" do
output = `inline -h` output = `inline -h`
expected_output = <<~OUTPUT expected_output = <<~OUTPUT
Command: Command:
@ -31,19 +31,10 @@ RSpec.describe 'Inline' do
expect(output).to eq(expected_output) expect(output).to eq(expected_output)
end end
it 'with option_one', if: RUBY_VERSION < '2.4' do it "with underscored option_one" do
output = `inline first_arg --option-one=test2 -bd test3`
expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \
'Options: {:option_with_default=>"test3", :option_one=>"test2", :boolean_option=>true}' \
"\n"
)
end
it 'with underscored option_one', if: RUBY_VERSION >= '2.4' do
output = `inline first_arg -1 test2 -bd test3` output = `inline first_arg -1 test2 -bd test3`
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
'Options: {:option_with_default=>"test3", :option_one=>"test2", :boolean_option=>true}' \ 'Options: {:option_with_default=>"test3", :option_one=>"test2", :boolean_option=>true}' \
"\n" "\n"
) )

View File

@ -1,10 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'open3' require "open3"
RSpec.describe 'Rendering' do RSpec.describe "Rendering" do
it 'prints available commands for unknown command' do it "prints available commands for unknown command" do
_, stderr, = Open3.capture3('foo unknown') _, stderr, = Open3.capture3("foo unknown")
expected = <<~DESC expected = <<~DESC
Commands: Commands:

View File

@ -1,19 +1,19 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'open3' require "open3"
RSpec.describe 'Single command' do RSpec.describe "Single command" do
context 'with command' do context "with command" do
let(:cmd) { 'baz' } let(:cmd) { "baz" }
it 'shows usage' do it "shows usage" do
_, stderr, = Open3.capture3('baz') _, stderr, = Open3.capture3("baz")
expect(stderr).to eq( expect(stderr).to eq(
"ERROR: \"#{cmd}\" was called with no arguments\nUsage: \"#{cmd} MANDATORY_ARG\"\n" "ERROR: \"#{cmd}\" was called with no arguments\nUsage: \"#{cmd} MANDATORY_ARG\"\n"
) )
end end
it 'shows help' do it "shows help" do
output = `baz -h` output = `baz -h`
expected_output = <<~OUTPUT expected_output = <<~OUTPUT
Command: Command:
@ -38,25 +38,25 @@ RSpec.describe 'Single command' do
expect(output).to eq(expected_output) expect(output).to eq(expected_output)
end end
it 'with option_one' do it "with option_one" do
output = `baz first_arg --option-one=test2` output = `baz first_arg --option-one=test2`
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test\", :option_one=>\"test2\"}\n" "Options: {:option_with_default=>\"test\", :option_one=>\"test2\"}\n"
) )
end end
it 'with combination of aliases' do it "with combination of aliases" do
output = `baz first_arg -bd test3` output = `baz first_arg -bd test3`
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test3\", :boolean_option=>true}\n" "Options: {:option_with_default=>\"test3\", :boolean_option=>true}\n"
) )
end end
end end
context 'root command with arguments and subcommands' do context "root command with arguments and subcommands" do
it 'with arguments' do it "with arguments" do
output = `foo root-command "hello world"` output = `foo root-command "hello world"`
expected = <<~DESC expected = <<~DESC
@ -67,7 +67,7 @@ RSpec.describe 'Single command' do
expect(output).to eq(expected) expect(output).to eq(expected)
end end
it 'with options' do it "with options" do
output = `foo root-command "hello world" --root-command-option="bye world"` output = `foo root-command "hello world" --root-command-option="bye world"`
expected = <<~DESC expected = <<~DESC

View File

@ -1,10 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'open3' require "open3"
RSpec.describe 'Subcommands' do RSpec.describe "Subcommands" do
context 'works with params' do context "works with params" do
it 'with help param' do it "with help param" do
output = `foo generate model --help` output = `foo generate model --help`
expected = <<~DESC expected = <<~DESC
@ -33,8 +33,8 @@ RSpec.describe 'Subcommands' do
end end
end end
context 'works with root command subcommands' do context "works with root command subcommands" do
it 'with params' do it "with params" do
output = `foo root-command sub-command "hello world"` output = `foo root-command sub-command "hello world"`
expected = <<~DESC expected = <<~DESC
@ -45,7 +45,7 @@ RSpec.describe 'Subcommands' do
expect(output).to eq(expected) expect(output).to eq(expected)
end end
it 'with options' do it "with options" do
option = '--root-command-sub-command-option="bye world"' option = '--root-command-sub-command-option="bye world"'
output = `foo root-command sub-command "hello world" #{option}` output = `foo root-command sub-command "hello world" #{option}`

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe 'Third-party gems' do RSpec.describe "Third-party gems" do
it 'allows to add callbacks as a block' do it "allows to add callbacks as a block" do
output = `foo callbacks . --url=https://hanamirb.test` output = `foo callbacks . --url=https://hanamirb.test`
expected = <<~OUTPUT expected = <<~OUTPUT

View File

@ -8,7 +8,7 @@ require_relative "./support/rspec"
%w[support unit].each do |dir| %w[support unit].each do |dir|
Dir[File.join(Dir.pwd, "spec", dir, "**", "*.rb")].each do |file| Dir[File.join(Dir.pwd, "spec", dir, "**", "*.rb")].each do |file|
unless RUBY_VERSION < "2.4.0" && file["support/warnings.rb"] unless file["support/warnings.rb"]
require_relative file require_relative file
end end
end end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'rspec/expectations' require "rspec/expectations"
RSpec::Matchers.define :have_content do |expected| RSpec::Matchers.define :have_content do |expected|
match do |actual| match do |actual|

View File

@ -1,9 +1,9 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# frozen_string_literal: true # frozen_string_literal: true
$LOAD_PATH.unshift __dir__ + '/../../lib' $LOAD_PATH.unshift __dir__ + "/../../lib"
require 'dry/cli' require "dry/cli"
require_relative 'baz_command' require_relative "baz_command"
Dry.CLI(Baz::CLI).call Dry.CLI(Baz::CLI).call

View File

@ -2,15 +2,15 @@
module Baz module Baz
class CLI < Dry::CLI::Command class CLI < Dry::CLI::Command
desc 'Baz command line interface' desc "Baz command line interface"
argument :mandatory_arg, required: true, aliases: %w[m], desc: 'Mandatory argument' argument :mandatory_arg, required: true, aliases: %w[m], desc: "Mandatory argument"
argument :optional_arg, aliases: %w[o], argument :optional_arg, aliases: %w[o],
desc: 'Optional argument (has to have default value in call method)' desc: "Optional argument (has to have default value in call method)"
option :option_one, aliases: %w[1], desc: 'Option one' option :option_one, aliases: %w[1], desc: "Option one"
option :boolean_option, aliases: %w[b], desc: 'Option boolean', type: :boolean option :boolean_option, aliases: %w[b], desc: "Option boolean", type: :boolean
option :option_with_default, aliases: %w[d], desc: 'Option default', default: 'test' option :option_with_default, aliases: %w[d], desc: "Option default", default: "test"
def call(mandatory_arg:, optional_arg: 'optional_arg', **options) def call(mandatory_arg:, optional_arg: "optional_arg", **options)
puts "mandatory_arg: #{mandatory_arg}. " \ puts "mandatory_arg: #{mandatory_arg}. " \
"optional_arg: #{optional_arg}. " \ "optional_arg: #{optional_arg}. " \
"Options: #{options.inspect}" "Options: #{options.inspect}"

View File

@ -2,8 +2,8 @@
# frozen_string_literal: true # frozen_string_literal: true
# rubocop:disable Metrics/LineLength # rubocop:disable Metrics/LineLength
$LOAD_PATH.unshift __dir__ + '/../../lib' $LOAD_PATH.unshift __dir__ + "/../../lib"
require 'dry/cli' require "dry/cli"
module Foo module Foo
module CLI module CLI
@ -15,10 +15,10 @@ module Foo
module Assets module Assets
class Precompile < Dry::CLI::Command class Precompile < Dry::CLI::Command
desc 'Precompile assets for deployment' desc "Precompile assets for deployment"
example [ example [
'FOO_ENV=production # Precompile assets for production environment' "FOO_ENV=production # Precompile assets for production environment"
] ]
def call(*); end def call(*); end
@ -26,12 +26,12 @@ module Foo
end end
class Console < Dry::CLI::Command class Console < Dry::CLI::Command
desc 'Starts Foo console' desc "Starts Foo console"
option :engine, desc: 'Force a console engine', values: %w[irb pry ripl] option :engine, desc: "Force a console engine", values: %w[irb pry ripl]
example [ example [
' # Uses the bundled engine', " # Uses the bundled engine",
'--engine=pry # Force to use Pry' "--engine=pry # Force to use Pry"
] ]
def call(engine: nil, **) def call(engine: nil, **)
@ -41,57 +41,57 @@ module Foo
module DB module DB
class Apply < Dry::CLI::Command class Apply < Dry::CLI::Command
desc 'Migrate, dump the SQL schema, and delete the migrations (experimental)' desc "Migrate, dump the SQL schema, and delete the migrations (experimental)"
def call(*); end def call(*); end
end end
class Console < Dry::CLI::Command class Console < Dry::CLI::Command
desc 'Starts a database console' desc "Starts a database console"
def call(*); end def call(*); end
end end
class Create < Dry::CLI::Command class Create < Dry::CLI::Command
desc 'Create the database (only for development/test)' desc "Create the database (only for development/test)"
def call(*); end def call(*); end
end end
class Drop < Dry::CLI::Command class Drop < Dry::CLI::Command
desc 'Drop the database (only for development/test)' desc "Drop the database (only for development/test)"
def call(*); end def call(*); end
end end
class Migrate < Dry::CLI::Command class Migrate < Dry::CLI::Command
desc 'Migrate the database' desc "Migrate the database"
argument :version, desc: 'The target version of the migration (see `foo db version`)' argument :version, desc: "The target version of the migration (see `foo db version`)"
example [ example [
' # Migrate to the last version', " # Migrate to the last version",
'20170721120747 # Migrate to a specific version' "20170721120747 # Migrate to a specific version"
] ]
def call(*); end def call(*); end
end end
class Prepare < Dry::CLI::Command class Prepare < Dry::CLI::Command
desc 'Drop, create, and migrate the database (only for development/test)' desc "Drop, create, and migrate the database (only for development/test)"
def call(*); end def call(*); end
end end
class Version < Dry::CLI::Command class Version < Dry::CLI::Command
desc 'Print the current migrated version' desc "Print the current migrated version"
def call(*); end def call(*); end
end end
class Rollback < Dry::CLI::Command class Rollback < Dry::CLI::Command
desc 'Rollback the database' desc "Rollback the database"
argument :steps, desc: 'Number of versions to rollback', default: 1 argument :steps, desc: "Number of versions to rollback", default: 1
def call(steps:, **) def call(steps:, **)
puts steps puts steps
@ -101,15 +101,15 @@ module Foo
module Destroy module Destroy
class Action < Dry::CLI::Command class Action < Dry::CLI::Command
desc 'Destroy an action from app' desc "Destroy an action from app"
example [ example [
'web home#index # Basic usage', "web home#index # Basic usage",
'admin users#index # Destroy from `admin` app' "admin users#index # Destroy from `admin` app"
] ]
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
argument :action, required: true, desc: 'The action name (eg. `home#index`)' argument :action, required: true, desc: "The action name (eg. `home#index`)"
def call(app:, action:, **) def call(app:, action:, **)
puts "destroy action - app: #{app}, action: #{action}" puts "destroy action - app: #{app}, action: #{action}"
@ -117,48 +117,48 @@ module Foo
end end
class App < Dry::CLI::Command class App < Dry::CLI::Command
desc 'Destroy an app' desc "Destroy an app"
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
example [ example [
'admin # Destroy `admin` app' "admin # Destroy `admin` app"
] ]
def call(*); end def call(*); end
end end
class Mailer < Dry::CLI::Command class Mailer < Dry::CLI::Command
desc 'Destroy a mailer' desc "Destroy a mailer"
argument :mailer, required: true, desc: 'The mailer name (eg. `welcome`)' argument :mailer, required: true, desc: "The mailer name (eg. `welcome`)"
example [ example [
'welcome # Destroy `WelcomeMailer` mailer' "welcome # Destroy `WelcomeMailer` mailer"
] ]
def call(*); end def call(*); end
end end
class Migration < Dry::CLI::Command class Migration < Dry::CLI::Command
desc 'Destroy a migration' desc "Destroy a migration"
argument :migration, required: true, desc: 'The migration name (eg. `create_users`)' argument :migration, required: true, desc: "The migration name (eg. `create_users`)"
example [ example [
'create_users # Destroy `db/migrations/20170721120747_create_users.rb`' "create_users # Destroy `db/migrations/20170721120747_create_users.rb`"
] ]
def call(*); end def call(*); end
end end
class Model < Dry::CLI::Command class Model < Dry::CLI::Command
desc 'Destroy a model' desc "Destroy a model"
argument :model, required: true, desc: 'The model name (eg. `user`)' argument :model, required: true, desc: "The model name (eg. `user`)"
example [ example [
'user # Destroy `User` entity and `UserRepository` repository' "user # Destroy `User` entity and `UserRepository` repository"
] ]
def call(*); end def call(*); end
@ -167,22 +167,22 @@ module Foo
module Generate module Generate
class Action < Dry::CLI::Command class Action < Dry::CLI::Command
desc 'Generate an action for app' desc "Generate an action for app"
example [ example [
'web home#index # Basic usage', "web home#index # Basic usage",
'admin home#index # Generate for `admin` app', "admin home#index # Generate for `admin` app",
'web home#index --url=/ # Specify URL', "web home#index --url=/ # Specify URL",
'web sessions#destroy --method=GET # Specify HTTP method', "web sessions#destroy --method=GET # Specify HTTP method",
'web books#create --skip-view # Skip view and template' "web books#create --skip-view # Skip view and template"
] ]
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
argument :action, required: true, desc: 'The action name (eg. `home#index`)' argument :action, required: true, desc: "The action name (eg. `home#index`)"
option :url, desc: 'The action URL' option :url, desc: "The action URL"
option :method, desc: 'The action HTTP method' option :method, desc: "The action HTTP method"
option :skip_view, type: :boolean, default: false, desc: 'Skip view and template' option :skip_view, type: :boolean, default: false, desc: "Skip view and template"
def call(app:, action:, **options) def call(app:, action:, **options)
puts "generate action - app: #{app}, action: #{action}, options: #{options.inspect}" puts "generate action - app: #{app}, action: #{action}, options: #{options.inspect}"
@ -190,30 +190,30 @@ module Foo
end end
class App < Dry::CLI::Command class App < Dry::CLI::Command
desc 'Generate an app' desc "Generate an app"
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
option :application_base_url, desc: 'The app base URL (eg. `/api/v1`)' option :application_base_url, desc: "The app base URL (eg. `/api/v1`)"
example [ example [
'admin # Generate `admin` app', "admin # Generate `admin` app",
'api --application-base-url=/api/v1 # Generate `api` app and mount at `/api/v1`' "api --application-base-url=/api/v1 # Generate `api` app and mount at `/api/v1`"
] ]
def call(*); end def call(*); end
end end
class Mailer < Dry::CLI::Command class Mailer < Dry::CLI::Command
desc 'Generate a mailer' desc "Generate a mailer"
argument :mailer, required: true, desc: 'The mailer name (eg. `welcome`)' argument :mailer, required: true, desc: "The mailer name (eg. `welcome`)"
option :from, desc: 'The default `from` field of the mail' option :from, desc: "The default `from` field of the mail"
option :to, desc: 'The default `to` field of the mail' option :to, desc: "The default `to` field of the mail"
option :subject, desc: 'The mail subject' option :subject, desc: "The mail subject"
example [ example [
'welcome # Basic usage', "welcome # Basic usage",
'welcome --from="noreply@example.com" # Generate with default `from` value', 'welcome --from="noreply@example.com" # Generate with default `from` value',
'announcement --to="users@example.com" # Generate with default `to` value', 'announcement --to="users@example.com" # Generate with default `to` value',
'forgot_password --subject="Your password reset" # Generate with default `subject`' 'forgot_password --subject="Your password reset" # Generate with default `subject`'
@ -223,26 +223,26 @@ module Foo
end end
class Migration < Dry::CLI::Command class Migration < Dry::CLI::Command
desc 'Generate a migration' desc "Generate a migration"
argument :migration, required: true, desc: 'The migration name (eg. `create_users`)' argument :migration, required: true, desc: "The migration name (eg. `create_users`)"
example [ example [
'create_users # Generate `db/migrations/20170721120747_create_users.rb`' "create_users # Generate `db/migrations/20170721120747_create_users.rb`"
] ]
def call(*); end def call(*); end
end end
class Model < Dry::CLI::Command class Model < Dry::CLI::Command
desc 'Generate a model' desc "Generate a model"
argument :model, required: true, desc: 'Model name (eg. `user`)' argument :model, required: true, desc: "Model name (eg. `user`)"
option :skip_migration, type: :boolean, default: false, desc: 'Skip migration' option :skip_migration, type: :boolean, default: false, desc: "Skip migration"
example [ example [
'user # Generate `User` entity, `UserRepository` repository, and the migration', "user # Generate `User` entity, `UserRepository` repository, and the migration",
'user --skip-migration # Generate `User` entity and `UserRepository` repository' "user --skip-migration # Generate `User` entity and `UserRepository` repository"
] ]
def call(model:, **) def call(model:, **)
@ -251,13 +251,13 @@ module Foo
end end
class Secret < Dry::CLI::Command class Secret < Dry::CLI::Command
desc 'Generate session secret' desc "Generate session secret"
argument :app, desc: 'The application name (eg. `web`)' argument :app, desc: "The application name (eg. `web`)"
example [ example [
' # Prints secret (eg. `6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)', " # Prints secret (eg. `6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)",
'web # Prints session secret (eg. `WEB_SESSIONS_SECRET=6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)' "web # Prints session secret (eg. `WEB_SESSIONS_SECRET=6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)"
] ]
def call(app: nil, **) def call(app: nil, **)
@ -267,22 +267,22 @@ module Foo
end end
class New < Dry::CLI::Command class New < Dry::CLI::Command
desc 'Generate a new Foo project' desc "Generate a new Foo project"
argument :project, required: true argument :project, required: true
option :database, desc: 'Database (sqlite/postgres/mysql)', default: 'sqlite', aliases: ['-d', '--db'] option :database, desc: "Database (sqlite/postgres/mysql)", default: "sqlite", aliases: ["-d", "--db"]
option :application_name, desc: 'App name', default: 'web' option :application_name, desc: "App name", default: "web"
option :application_base_url, desc: 'App base URL', default: '/' option :application_base_url, desc: "App base URL", default: "/"
option :template, desc: 'Template engine (erb/haml/slim)', default: 'erb' option :template, desc: "Template engine (erb/haml/slim)", default: "erb"
option :test, desc: 'Project testing framework (minitest/rspec)', default: 'minitest' option :test, desc: "Project testing framework (minitest/rspec)", default: "minitest"
option :foo_head, desc: 'Use Foo HEAD (true/false)', type: :boolean, default: false option :foo_head, desc: "Use Foo HEAD (true/false)", type: :boolean, default: false
example [ example [
'bookshelf # Basic usage', "bookshelf # Basic usage",
'bookshelf --test=rspec # Setup RSpec testing framework', "bookshelf --test=rspec # Setup RSpec testing framework",
'bookshelf --database=postgres # Setup Postgres database', "bookshelf --database=postgres # Setup Postgres database",
'bookshelf --template=slim # Setup Slim template engine', "bookshelf --template=slim # Setup Slim template engine",
'bookshelf --foo-head # Use Foo HEAD' "bookshelf --foo-head # Use Foo HEAD"
] ]
def call(project:, **) def call(project:, **)
@ -291,29 +291,29 @@ module Foo
end end
class Routes < Dry::CLI::Command class Routes < Dry::CLI::Command
desc 'Print routes' desc "Print routes"
def call(*); end def call(*); end
end end
class Server < Dry::CLI::Command class Server < Dry::CLI::Command
desc 'Start Foo server (only for development)' desc "Start Foo server (only for development)"
option :server, desc: 'Force a server engine (eg, webrick, puma, thin, etc..)' option :server, desc: "Force a server engine (eg, webrick, puma, thin, etc..)"
option :host, desc: 'The host address to bind to' option :host, desc: "The host address to bind to"
option :port, desc: 'The port to run the server on', aliases: ['-p'] option :port, desc: "The port to run the server on", aliases: ["-p"]
option :debug, desc: 'Turn on debug output' option :debug, desc: "Turn on debug output"
option :warn, desc: 'Turn on warnings' option :warn, desc: "Turn on warnings"
option :daemonize, desc: 'Daemonize the server' option :daemonize, desc: "Daemonize the server"
option :pid, desc: 'Path to write a pid file after daemonize' option :pid, desc: "Path to write a pid file after daemonize"
option :code_reloading, desc: 'Code reloading', type: :boolean, default: true option :code_reloading, desc: "Code reloading", type: :boolean, default: true
example [ example [
' # Basic usage (it uses the bundled server engine)', " # Basic usage (it uses the bundled server engine)",
'--server=webrick # Force `webrick` server engine', "--server=webrick # Force `webrick` server engine",
'--host=0.0.0.0 # Bind to a host', "--host=0.0.0.0 # Bind to a host",
'--port=2306 # Bind to a port', "--port=2306 # Bind to a port",
'--no-code-reloading # Disable code reloading' "--no-code-reloading # Disable code reloading"
] ]
def call(options) def call(options)
@ -322,18 +322,18 @@ module Foo
end end
class Version < Dry::CLI::Command class Version < Dry::CLI::Command
desc 'Print Foo version' desc "Print Foo version"
def call(*) def call(*)
puts 'v1.0.0' puts "v1.0.0"
end end
end end
class Exec < Dry::CLI::Command class Exec < Dry::CLI::Command
desc 'Execute a task' desc "Execute a task"
argument :task, desc: 'Task to execute', type: :string, required: true argument :task, desc: "Task to execute", type: :string, required: true
argument :dirs, desc: 'Directories', type: :array, required: false argument :dirs, desc: "Directories", type: :array, required: false
def call(task:, dirs: [], **) def call(task:, dirs: [], **)
puts "exec - Task: #{task} - Directories: #{dirs.inspect}" puts "exec - Task: #{task} - Directories: #{dirs.inspect}"
@ -347,7 +347,7 @@ module Foo
end end
class Greeting < Dry::CLI::Command class Greeting < Dry::CLI::Command
argument :response, default: 'Hello World' argument :response, default: "Hello World"
option :person option :person
@ -357,36 +357,36 @@ module Foo
end end
class VariadicArguments < Dry::CLI::Command class VariadicArguments < Dry::CLI::Command
desc 'accept multiple arguments at the end of the command' desc "accept multiple arguments at the end of the command"
def call(**options) def call(**options)
puts "Unused Arguments: #{options[:args].join(', ')}" puts "Unused Arguments: #{options[:args].join(", ")}"
end end
end end
class MandatoryAndVariadicArguments < Dry::CLI::Command class MandatoryAndVariadicArguments < Dry::CLI::Command
desc 'require one command and accept multiple unused arguments' desc "require one command and accept multiple unused arguments"
argument :first, desc: 'mandatory first argument', required: true argument :first, desc: "mandatory first argument", required: true
def call(first:, **options) def call(first:, **options)
puts "first: #{first}" puts "first: #{first}"
puts "Unused Arguments: #{options[:args].join(', ')}" puts "Unused Arguments: #{options[:args].join(", ")}"
end end
end end
class MandatoryOptionsAndVariadicArguments < Dry::CLI::Command class MandatoryOptionsAndVariadicArguments < Dry::CLI::Command
desc 'require one command, accept options and multiple unused arguments' desc "require one command, accept options and multiple unused arguments"
argument :first, desc: 'mandatory first argument', required: true argument :first, desc: "mandatory first argument", required: true
option :url, desc: 'The action URL' option :url, desc: "The action URL"
option :method, desc: 'The action HTTP method' option :method, desc: "The action HTTP method"
def call(first:, **options) def call(first:, **options)
puts "first: #{first}" puts "first: #{first}"
puts "url: #{options[:url]}" puts "url: #{options[:url]}"
puts "method: #{options[:method]}" puts "method: #{options[:method]}"
puts "Unused Arguments: #{options[:args].join(', ')}" puts "Unused Arguments: #{options[:args].join(", ")}"
end end
end end
@ -399,9 +399,9 @@ module Foo
end end
class RootCommand < Dry::CLI::Command class RootCommand < Dry::CLI::Command
desc 'Root command with arguments and subcommands' desc "Root command with arguments and subcommands"
argument :root_command_argument, desc: 'Root command argument', required: true argument :root_command_argument, desc: "Root command argument", required: true
option :root_command_option, desc: 'Root command option' option :root_command_option, desc: "Root command option"
def call(**params) def call(**params)
puts "I'm a root-command argument:#{params[:root_command_argument]}" puts "I'm a root-command argument:#{params[:root_command_argument]}"
@ -411,9 +411,9 @@ module Foo
module RootCommands module RootCommands
class SubCommand < Dry::CLI::Command class SubCommand < Dry::CLI::Command
desc 'Root command sub command' desc "Root command sub command"
argument :root_command_sub_command_argument, desc: 'Root command sub command argument', required: true argument :root_command_sub_command_argument, desc: "Root command sub command argument", required: true
option :root_command_sub_command_option, desc: 'Root command sub command option' option :root_command_sub_command_option, desc: "Root command sub command option"
def call(**params) def call(**params)
puts "I'm a root-command sub-command argument:#{params[:root_command_sub_command_argument]}" puts "I'm a root-command sub-command argument:#{params[:root_command_sub_command_argument]}"
@ -425,56 +425,56 @@ module Foo
end end
end end
Foo::CLI::Commands.register 'assets precompile', Foo::CLI::Commands::Assets::Precompile Foo::CLI::Commands.register "assets precompile", Foo::CLI::Commands::Assets::Precompile
Foo::CLI::Commands.register 'console', Foo::CLI::Commands::Console Foo::CLI::Commands.register "console", Foo::CLI::Commands::Console
Foo::CLI::Commands.register 'db' do |prefix| Foo::CLI::Commands.register "db" do |prefix|
prefix.register 'apply', Foo::CLI::Commands::DB::Apply prefix.register "apply", Foo::CLI::Commands::DB::Apply
prefix.register 'console', Foo::CLI::Commands::DB::Console prefix.register "console", Foo::CLI::Commands::DB::Console
prefix.register 'create', Foo::CLI::Commands::DB::Create prefix.register "create", Foo::CLI::Commands::DB::Create
prefix.register 'drop', Foo::CLI::Commands::DB::Drop prefix.register "drop", Foo::CLI::Commands::DB::Drop
prefix.register 'migrate', Foo::CLI::Commands::DB::Migrate prefix.register "migrate", Foo::CLI::Commands::DB::Migrate
prefix.register 'prepare', Foo::CLI::Commands::DB::Prepare prefix.register "prepare", Foo::CLI::Commands::DB::Prepare
prefix.register 'version', Foo::CLI::Commands::DB::Version prefix.register "version", Foo::CLI::Commands::DB::Version
prefix.register 'rollback', Foo::CLI::Commands::DB::Rollback prefix.register "rollback", Foo::CLI::Commands::DB::Rollback
end end
Foo::CLI::Commands.register 'destroy', aliases: ['d'] do |prefix| Foo::CLI::Commands.register "destroy", aliases: ["d"] do |prefix|
prefix.register 'action', Foo::CLI::Commands::Destroy::Action prefix.register "action", Foo::CLI::Commands::Destroy::Action
prefix.register 'app', Foo::CLI::Commands::Destroy::App prefix.register "app", Foo::CLI::Commands::Destroy::App
prefix.register 'mailer', Foo::CLI::Commands::Destroy::Mailer prefix.register "mailer", Foo::CLI::Commands::Destroy::Mailer
prefix.register 'migration', Foo::CLI::Commands::Destroy::Migration prefix.register "migration", Foo::CLI::Commands::Destroy::Migration
prefix.register 'model', Foo::CLI::Commands::Destroy::Model prefix.register "model", Foo::CLI::Commands::Destroy::Model
end end
Foo::CLI::Commands.register 'generate', aliases: ['g'] do |prefix| Foo::CLI::Commands.register "generate", aliases: ["g"] do |prefix|
prefix.register 'action', Foo::CLI::Commands::Generate::Action prefix.register "action", Foo::CLI::Commands::Generate::Action
prefix.register 'app', Foo::CLI::Commands::Generate::App prefix.register "app", Foo::CLI::Commands::Generate::App
prefix.register 'mailer', Foo::CLI::Commands::Generate::Mailer prefix.register "mailer", Foo::CLI::Commands::Generate::Mailer
prefix.register 'migration', Foo::CLI::Commands::Generate::Migration prefix.register "migration", Foo::CLI::Commands::Generate::Migration
prefix.register 'model', Foo::CLI::Commands::Generate::Model prefix.register "model", Foo::CLI::Commands::Generate::Model
prefix.register 'secret', Foo::CLI::Commands::Generate::Secret prefix.register "secret", Foo::CLI::Commands::Generate::Secret
end end
Foo::CLI::Commands.register 'new', Foo::CLI::Commands::New Foo::CLI::Commands.register "new", Foo::CLI::Commands::New
Foo::CLI::Commands.register 'routes', Foo::CLI::Commands::Routes Foo::CLI::Commands.register "routes", Foo::CLI::Commands::Routes
Foo::CLI::Commands.register 'server', Foo::CLI::Commands::Server, aliases: ['s'] Foo::CLI::Commands.register "server", Foo::CLI::Commands::Server, aliases: ["s"]
Foo::CLI::Commands.register 'version', Foo::CLI::Commands::Version, aliases: ['v', '-v', '--version'] Foo::CLI::Commands.register "version", Foo::CLI::Commands::Version, aliases: ["v", "-v", "--version"]
Foo::CLI::Commands.register 'exec', Foo::CLI::Commands::Exec Foo::CLI::Commands.register "exec", Foo::CLI::Commands::Exec
Foo::CLI::Commands.register 'hello', Foo::CLI::Commands::Hello Foo::CLI::Commands.register "hello", Foo::CLI::Commands::Hello
Foo::CLI::Commands.register 'greeting', Foo::CLI::Commands::Greeting Foo::CLI::Commands.register "greeting", Foo::CLI::Commands::Greeting
Foo::CLI::Commands.register 'sub command', Foo::CLI::Commands::Sub::Command Foo::CLI::Commands.register "sub command", Foo::CLI::Commands::Sub::Command
Foo::CLI::Commands.register 'root-command', Foo::CLI::Commands::RootCommand Foo::CLI::Commands.register "root-command", Foo::CLI::Commands::RootCommand
Foo::CLI::Commands.register 'root-command sub-command', Foo::CLI::Commands::RootCommands::SubCommand Foo::CLI::Commands.register "root-command sub-command", Foo::CLI::Commands::RootCommands::SubCommand
Foo::CLI::Commands.register 'variadic default', Foo::CLI::Commands::VariadicArguments Foo::CLI::Commands.register "variadic default", Foo::CLI::Commands::VariadicArguments
Foo::CLI::Commands.register 'variadic with-mandatory', Foo::CLI::Commands::MandatoryAndVariadicArguments Foo::CLI::Commands.register "variadic with-mandatory", Foo::CLI::Commands::MandatoryAndVariadicArguments
Foo::CLI::Commands.register 'variadic with-mandatory-and-options', Foo::CLI::Commands::MandatoryOptionsAndVariadicArguments Foo::CLI::Commands.register "variadic with-mandatory-and-options", Foo::CLI::Commands::MandatoryOptionsAndVariadicArguments
module Foo module Foo
module Webpack module Webpack
module CLI module CLI
class Generate < Dry::CLI::Command class Generate < Dry::CLI::Command
desc 'Generate webpack configuration' desc "Generate webpack configuration"
option :apps, desc: 'Generate webpack apps', type: :array option :apps, desc: "Generate webpack apps", type: :array
def call(apps: [], **) def call(apps: [], **)
puts "generate webpack. Apps: #{apps}" puts "generate webpack. Apps: #{apps}"
@ -482,23 +482,23 @@ module Foo
end end
class Hello < Dry::CLI::Command class Hello < Dry::CLI::Command
desc 'Print a greeting' desc "Print a greeting"
def call(*) def call(*)
puts 'hello from webpack' puts "hello from webpack"
end end
end end
class SubCommand < Dry::CLI::Command class SubCommand < Dry::CLI::Command
desc 'Override a subcommand' desc "Override a subcommand"
def call(**) def call(**)
puts 'override from webpack' puts "override from webpack"
end end
end end
class CallbacksCommand < Dry::CLI::Command class CallbacksCommand < Dry::CLI::Command
desc 'Command with callbacks' desc "Command with callbacks"
argument :dir, required: true argument :dir, required: true
option :url option :url
@ -510,19 +510,19 @@ module Foo
end end
end end
Foo::CLI::Commands.register 'generate webpack', Foo::Webpack::CLI::Generate Foo::CLI::Commands.register "generate webpack", Foo::Webpack::CLI::Generate
Foo::CLI::Commands.register 'hello', Foo::Webpack::CLI::Hello Foo::CLI::Commands.register "hello", Foo::Webpack::CLI::Hello
Foo::CLI::Commands.register 'sub command', Foo::Webpack::CLI::SubCommand Foo::CLI::Commands.register "sub command", Foo::Webpack::CLI::SubCommand
Foo::CLI::Commands.register 'callbacks', Foo::Webpack::CLI::CallbacksCommand Foo::CLI::Commands.register "callbacks", Foo::Webpack::CLI::CallbacksCommand
# we need to be sure that command will not override with nil command # we need to be sure that command will not override with nil command
Foo::CLI::Commands.register 'generate webpack', nil Foo::CLI::Commands.register "generate webpack", nil
Foo::CLI::Commands.before('callbacks') do |args| Foo::CLI::Commands.before("callbacks") do |args|
puts "before command callback #{self.class.name} #{args.inspect}" puts "before command callback #{self.class.name} #{args.inspect}"
end end
Foo::CLI::Commands.after('callbacks') do |args| Foo::CLI::Commands.after("callbacks") do |args|
puts "after command callback #{self.class.name} #{args.inspect}" puts "after command callback #{self.class.name} #{args.inspect}"
end end
@ -577,10 +577,10 @@ module Callbacks
end end
# rubocop:enable Metrics/LineLength # rubocop:enable Metrics/LineLength
Foo::CLI::Commands.before('callbacks', Callbacks::BeforeClass) Foo::CLI::Commands.before("callbacks", Callbacks::BeforeClass)
Foo::CLI::Commands.after('callbacks', Callbacks::AfterClass) Foo::CLI::Commands.after("callbacks", Callbacks::AfterClass)
Foo::CLI::Commands.before('callbacks', Callbacks::Before.new) Foo::CLI::Commands.before("callbacks", Callbacks::Before.new)
Foo::CLI::Commands.after('callbacks', Callbacks::After.new) Foo::CLI::Commands.after("callbacks", Callbacks::After.new)
cli = Dry::CLI.new(Foo::CLI::Commands) cli = Dry::CLI.new(Foo::CLI::Commands)
cli.call cli.call

View File

@ -1,19 +1,19 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# frozen_string_literal: true # frozen_string_literal: true
$LOAD_PATH.unshift __dir__ + '/../../../lib' $LOAD_PATH.unshift __dir__ + "/../../../lib"
require 'dry/cli' require "dry/cli"
require_relative '../../../lib/dry/cli/inline' require_relative "../../../lib/dry/cli/inline"
desc 'Baz command line interface' desc "Baz command line interface"
argument :mandatory_arg, required: true, aliases: %w[m], desc: 'Mandatory argument' argument :mandatory_arg, required: true, aliases: %w[m], desc: "Mandatory argument"
argument :optional_arg, aliases: %w[o], argument :optional_arg, aliases: %w[o],
desc: 'Optional argument (has to have default value in call method)' desc: "Optional argument (has to have default value in call method)"
option :option_one, aliases: %w[1], desc: 'Option one' option :option_one, aliases: %w[1], desc: "Option one"
option :boolean_option, aliases: %w[b], desc: 'Option boolean', type: :boolean option :boolean_option, aliases: %w[b], desc: "Option boolean", type: :boolean
option :option_with_default, aliases: %w[d], desc: 'Option default', default: 'test' option :option_with_default, aliases: %w[d], desc: "Option default", default: "test"
run do |mandatory_arg:, optional_arg: 'optional_arg', **options| run do |mandatory_arg:, optional_arg: "optional_arg", **options|
puts "mandatory_arg: #{mandatory_arg}. " \ puts "mandatory_arg: #{mandatory_arg}. " \
"optional_arg: #{optional_arg}. " \ "optional_arg: #{optional_arg}. " \
"Options: #{options.inspect}" "Options: #{options.inspect}"

View File

@ -9,7 +9,7 @@ module Bar
def call(*); end def call(*); end
end end
register 'alpha', Alpha register "alpha", Alpha
end end
end end
end end

View File

@ -7,10 +7,10 @@ module Commands
module Assets module Assets
class Precompile < Dry::CLI::Command class Precompile < Dry::CLI::Command
desc 'Precompile assets for deployment' desc "Precompile assets for deployment"
example [ example [
'FOO_ENV=production # Precompile assets for production environment' "FOO_ENV=production # Precompile assets for production environment"
] ]
def call(*); end def call(*); end
@ -18,12 +18,12 @@ module Commands
end end
class Console < Dry::CLI::Command class Console < Dry::CLI::Command
desc 'Starts Foo console' desc "Starts Foo console"
option :engine, desc: 'Force a console engine', values: %w[irb pry ripl] option :engine, desc: "Force a console engine", values: %w[irb pry ripl]
example [ example [
' # Uses the bundled engine', " # Uses the bundled engine",
'--engine=pry # Force to use Pry' "--engine=pry # Force to use Pry"
] ]
def call(engine: nil, **) def call(engine: nil, **)
@ -33,57 +33,57 @@ module Commands
module DB module DB
class Apply < Dry::CLI::Command class Apply < Dry::CLI::Command
desc 'Migrate, dump the SQL schema, and delete the migrations (experimental)' desc "Migrate, dump the SQL schema, and delete the migrations (experimental)"
def call(*); end def call(*); end
end end
class Console < Dry::CLI::Command class Console < Dry::CLI::Command
desc 'Starts a database console' desc "Starts a database console"
def call(*); end def call(*); end
end end
class Create < Dry::CLI::Command class Create < Dry::CLI::Command
desc 'Create the database (only for development/test)' desc "Create the database (only for development/test)"
def call(*); end def call(*); end
end end
class Drop < Dry::CLI::Command class Drop < Dry::CLI::Command
desc 'Drop the database (only for development/test)' desc "Drop the database (only for development/test)"
def call(*); end def call(*); end
end end
class Migrate < Dry::CLI::Command class Migrate < Dry::CLI::Command
desc 'Migrate the database' desc "Migrate the database"
argument :version, desc: 'The target version of the migration (see `foo db version`)' argument :version, desc: "The target version of the migration (see `foo db version`)"
example [ example [
' # Migrate to the last version', " # Migrate to the last version",
'20170721120747 # Migrate to a specific version' "20170721120747 # Migrate to a specific version"
] ]
def call(*); end def call(*); end
end end
class Prepare < Dry::CLI::Command class Prepare < Dry::CLI::Command
desc 'Drop, create, and migrate the database (only for development/test)' desc "Drop, create, and migrate the database (only for development/test)"
def call(*); end def call(*); end
end end
class Version < Dry::CLI::Command class Version < Dry::CLI::Command
desc 'Print the current migrated version' desc "Print the current migrated version"
def call(*); end def call(*); end
end end
class Rollback < Dry::CLI::Command class Rollback < Dry::CLI::Command
desc 'Rollback the database' desc "Rollback the database"
argument :steps, desc: 'Number of versions to rollback', default: 1 argument :steps, desc: "Number of versions to rollback", default: 1
def call(steps:, **) def call(steps:, **)
puts steps puts steps
@ -93,15 +93,15 @@ module Commands
module Destroy module Destroy
class Action < Dry::CLI::Command class Action < Dry::CLI::Command
desc 'Destroy an action from app' desc "Destroy an action from app"
example [ example [
'web home#index # Basic usage', "web home#index # Basic usage",
'admin users#index # Destroy from `admin` app' "admin users#index # Destroy from `admin` app"
] ]
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
argument :action, required: true, desc: 'The action name (eg. `home#index`)' argument :action, required: true, desc: "The action name (eg. `home#index`)"
def call(app:, action:, **) def call(app:, action:, **)
puts "destroy action - app: #{app}, action: #{action}" puts "destroy action - app: #{app}, action: #{action}"
@ -109,48 +109,48 @@ module Commands
end end
class App < Dry::CLI::Command class App < Dry::CLI::Command
desc 'Destroy an app' desc "Destroy an app"
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
example [ example [
'admin # Destroy `admin` app' "admin # Destroy `admin` app"
] ]
def call(*); end def call(*); end
end end
class Mailer < Dry::CLI::Command class Mailer < Dry::CLI::Command
desc 'Destroy a mailer' desc "Destroy a mailer"
argument :mailer, required: true, desc: 'The mailer name (eg. `welcome`)' argument :mailer, required: true, desc: "The mailer name (eg. `welcome`)"
example [ example [
'welcome # Destroy `WelcomeMailer` mailer' "welcome # Destroy `WelcomeMailer` mailer"
] ]
def call(*); end def call(*); end
end end
class Migration < Dry::CLI::Command class Migration < Dry::CLI::Command
desc 'Destroy a migration' desc "Destroy a migration"
argument :migration, required: true, desc: 'The migration name (eg. `create_users`)' argument :migration, required: true, desc: "The migration name (eg. `create_users`)"
example [ example [
'create_users # Destroy `db/migrations/20170721120747_create_users.rb`' "create_users # Destroy `db/migrations/20170721120747_create_users.rb`"
] ]
def call(*); end def call(*); end
end end
class Model < Dry::CLI::Command class Model < Dry::CLI::Command
desc 'Destroy a model' desc "Destroy a model"
argument :model, required: true, desc: 'The model name (eg. `user`)' argument :model, required: true, desc: "The model name (eg. `user`)"
example [ example [
'user # Destroy `User` entity and `UserRepository` repository' "user # Destroy `User` entity and `UserRepository` repository"
] ]
def call(*); end def call(*); end
@ -159,22 +159,22 @@ module Commands
module Generate module Generate
class Action < Dry::CLI::Command class Action < Dry::CLI::Command
desc 'Generate an action for app' desc "Generate an action for app"
example [ example [
'web home#index # Basic usage', "web home#index # Basic usage",
'admin home#index # Generate for `admin` app', "admin home#index # Generate for `admin` app",
'web home#index --url=/ # Specify URL', "web home#index --url=/ # Specify URL",
'web sessions#destroy --method=GET # Specify HTTP method', "web sessions#destroy --method=GET # Specify HTTP method",
'web books#create --skip-view # Skip view and template' "web books#create --skip-view # Skip view and template"
] ]
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
argument :action, required: true, desc: 'The action name (eg. `home#index`)' argument :action, required: true, desc: "The action name (eg. `home#index`)"
option :url, desc: 'The action URL' option :url, desc: "The action URL"
option :method, desc: 'The action HTTP method' option :method, desc: "The action HTTP method"
option :skip_view, type: :boolean, default: false, desc: 'Skip view and template' option :skip_view, type: :boolean, default: false, desc: "Skip view and template"
def call(app:, action:, **options) def call(app:, action:, **options)
puts "generate action - app: #{app}, action: #{action}, options: #{options.inspect}" puts "generate action - app: #{app}, action: #{action}, options: #{options.inspect}"
@ -182,30 +182,30 @@ module Commands
end end
class App < Dry::CLI::Command class App < Dry::CLI::Command
desc 'Generate an app' desc "Generate an app"
argument :app, required: true, desc: 'The application name (eg. `web`)' argument :app, required: true, desc: "The application name (eg. `web`)"
option :application_base_url, desc: 'The app base URL (eg. `/api/v1`)' option :application_base_url, desc: "The app base URL (eg. `/api/v1`)"
example [ example [
'admin # Generate `admin` app', "admin # Generate `admin` app",
'api --application-base-url=/api/v1 # Generate `api` app and mount at `/api/v1`' "api --application-base-url=/api/v1 # Generate `api` app and mount at `/api/v1`"
] ]
def call(*); end def call(*); end
end end
class Mailer < Dry::CLI::Command class Mailer < Dry::CLI::Command
desc 'Generate a mailer' desc "Generate a mailer"
argument :mailer, required: true, desc: 'The mailer name (eg. `welcome`)' argument :mailer, required: true, desc: "The mailer name (eg. `welcome`)"
option :from, desc: 'The default `from` field of the mail' option :from, desc: "The default `from` field of the mail"
option :to, desc: 'The default `to` field of the mail' option :to, desc: "The default `to` field of the mail"
option :subject, desc: 'The mail subject' option :subject, desc: "The mail subject"
example [ example [
'welcome # Basic usage', "welcome # Basic usage",
'welcome --from="noreply@example.com" # Generate with default `from` value', 'welcome --from="noreply@example.com" # Generate with default `from` value',
'announcement --to="users@example.com" # Generate with default `to` value', 'announcement --to="users@example.com" # Generate with default `to` value',
'forgot_password --subject="Your password reset" # Generate with default `subject`' 'forgot_password --subject="Your password reset" # Generate with default `subject`'
@ -215,26 +215,26 @@ module Commands
end end
class Migration < Dry::CLI::Command class Migration < Dry::CLI::Command
desc 'Generate a migration' desc "Generate a migration"
argument :migration, required: true, desc: 'The migration name (eg. `create_users`)' argument :migration, required: true, desc: "The migration name (eg. `create_users`)"
example [ example [
'create_users # Generate `db/migrations/20170721120747_create_users.rb`' "create_users # Generate `db/migrations/20170721120747_create_users.rb`"
] ]
def call(*); end def call(*); end
end end
class Model < Dry::CLI::Command class Model < Dry::CLI::Command
desc 'Generate a model' desc "Generate a model"
argument :model, required: true, desc: 'Model name (eg. `user`)' argument :model, required: true, desc: "Model name (eg. `user`)"
option :skip_migration, type: :boolean, default: false, desc: 'Skip migration' option :skip_migration, type: :boolean, default: false, desc: "Skip migration"
example [ example [
'user # Generate `User` entity, `UserRepository` repository, and the migration', "user # Generate `User` entity, `UserRepository` repository, and the migration",
'user --skip-migration # Generate `User` entity and `UserRepository` repository' "user --skip-migration # Generate `User` entity and `UserRepository` repository"
] ]
def call(model:, **) def call(model:, **)
@ -243,13 +243,13 @@ module Commands
end end
class Secret < Dry::CLI::Command class Secret < Dry::CLI::Command
desc 'Generate session secret' desc "Generate session secret"
argument :app, desc: 'The application name (eg. `web`)' argument :app, desc: "The application name (eg. `web`)"
example [ example [
' # Prints secret (eg. `6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)', " # Prints secret (eg. `6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)",
'web # Prints session secret (eg. `WEB_SESSIONS_SECRET=6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)' "web # Prints session secret (eg. `WEB_SESSIONS_SECRET=6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)"
] ]
def call(app: nil, **) def call(app: nil, **)
@ -259,22 +259,22 @@ module Commands
end end
class New < Dry::CLI::Command class New < Dry::CLI::Command
desc 'Generate a new Foo project' desc "Generate a new Foo project"
argument :project, required: true argument :project, required: true
option :database, desc: 'Database (sqlite/postgres/mysql)', default: 'sqlite', aliases: ['-d', '--db'] option :database, desc: "Database (sqlite/postgres/mysql)", default: "sqlite", aliases: ["-d", "--db"]
option :application_name, desc: 'App name', default: 'web' option :application_name, desc: "App name", default: "web"
option :application_base_url, desc: 'App base URL', default: '/' option :application_base_url, desc: "App base URL", default: "/"
option :template, desc: 'Template engine (erb/haml/slim)', default: 'erb' option :template, desc: "Template engine (erb/haml/slim)", default: "erb"
option :test, desc: 'Project testing framework (minitest/rspec)', default: 'minitest' option :test, desc: "Project testing framework (minitest/rspec)", default: "minitest"
option :foo_head, desc: 'Use Foo HEAD (true/false)', type: :boolean, default: false option :foo_head, desc: "Use Foo HEAD (true/false)", type: :boolean, default: false
example [ example [
'bookshelf # Basic usage', "bookshelf # Basic usage",
'bookshelf --test=rspec # Setup RSpec testing framework', "bookshelf --test=rspec # Setup RSpec testing framework",
'bookshelf --database=postgres # Setup Postgres database', "bookshelf --database=postgres # Setup Postgres database",
'bookshelf --template=slim # Setup Slim template engine', "bookshelf --template=slim # Setup Slim template engine",
'bookshelf --foo-head # Use Foo HEAD' "bookshelf --foo-head # Use Foo HEAD"
] ]
def call(project:, **) def call(project:, **)
@ -283,30 +283,30 @@ module Commands
end end
class Routes < Dry::CLI::Command class Routes < Dry::CLI::Command
desc 'Print routes' desc "Print routes"
def call(*); end def call(*); end
end end
class Server < Dry::CLI::Command class Server < Dry::CLI::Command
desc 'Start Foo server (only for development)' desc "Start Foo server (only for development)"
option :server, desc: 'Force a server engine (eg, webrick, puma, thin, etc..)' option :server, desc: "Force a server engine (eg, webrick, puma, thin, etc..)"
option :host, desc: 'The host address to bind to' option :host, desc: "The host address to bind to"
option :port, desc: 'The port to run the server on', aliases: ['-p', 'p', '--p'] option :port, desc: "The port to run the server on", aliases: ["-p", "p", "--p"]
option :debug, desc: 'Turn on debug output' option :debug, desc: "Turn on debug output"
option :warn, desc: 'Turn on warnings' option :warn, desc: "Turn on warnings"
option :daemonize, desc: 'Daemonize the server' option :daemonize, desc: "Daemonize the server"
option :pid, desc: 'Path to write a pid file after daemonize' option :pid, desc: "Path to write a pid file after daemonize"
option :code_reloading, desc: 'Code reloading', type: :boolean, default: true option :code_reloading, desc: "Code reloading", type: :boolean, default: true
option :deps, desc: 'List of extra dependencies', type: :array, default: %w[dep1 dep2] option :deps, desc: "List of extra dependencies", type: :array, default: %w[dep1 dep2]
example [ example [
' # Basic usage (it uses the bundled server engine)', " # Basic usage (it uses the bundled server engine)",
'--server=webrick # Force `webrick` server engine', "--server=webrick # Force `webrick` server engine",
'--host=0.0.0.0 # Bind to a host', "--host=0.0.0.0 # Bind to a host",
'--port=2306 # Bind to a port', "--port=2306 # Bind to a port",
'--no-code-reloading # Disable code reloading' "--no-code-reloading # Disable code reloading"
] ]
def call(**options) def call(**options)
@ -315,18 +315,18 @@ module Commands
end end
class Version < Dry::CLI::Command class Version < Dry::CLI::Command
desc 'Print Foo version' desc "Print Foo version"
def call(*) def call(*)
puts 'v1.0.0' puts "v1.0.0"
end end
end end
class Exec < Dry::CLI::Command class Exec < Dry::CLI::Command
desc 'Execute a task' desc "Execute a task"
argument :task, desc: 'Task to execute', type: :string, required: true argument :task, desc: "Task to execute", type: :string, required: true
argument :dirs, desc: 'Directories', type: :array, required: false argument :dirs, desc: "Directories", type: :array, required: false
def call(task:, dirs: [], **) def call(task:, dirs: [], **)
puts "exec - Task: #{task} - Directories: #{dirs.inspect}" puts "exec - Task: #{task} - Directories: #{dirs.inspect}"
@ -340,7 +340,7 @@ module Commands
end end
class Greeting < Dry::CLI::Command class Greeting < Dry::CLI::Command
argument :response, default: 'Hello World' argument :response, default: "Hello World"
option :person option :person
@ -350,45 +350,45 @@ module Commands
end end
class VariadicArguments < Dry::CLI::Command class VariadicArguments < Dry::CLI::Command
desc 'accept multiple arguments at the end of the command' desc "accept multiple arguments at the end of the command"
def call(**options) def call(**options)
puts "Unused Arguments: #{options[:args].join(', ')}" puts "Unused Arguments: #{options[:args].join(", ")}"
end end
end end
class MandatoryAndVariadicArguments < Dry::CLI::Command class MandatoryAndVariadicArguments < Dry::CLI::Command
desc 'require one command and accept multiple unused arguments' desc "require one command and accept multiple unused arguments"
argument :first, desc: 'mandatory first argument', required: true argument :first, desc: "mandatory first argument", required: true
def call(first:, **options) def call(first:, **options)
puts "first: #{first}" puts "first: #{first}"
puts "Unused Arguments: #{options[:args].join(', ')}" puts "Unused Arguments: #{options[:args].join(", ")}"
end end
end end
class MandatoryOptionsAndVariadicArguments < Dry::CLI::Command class MandatoryOptionsAndVariadicArguments < Dry::CLI::Command
desc 'require one command, accept options and multiple unused arguments' desc "require one command, accept options and multiple unused arguments"
argument :first, desc: 'mandatory first argument', required: true argument :first, desc: "mandatory first argument", required: true
option :url, desc: 'The action URL' option :url, desc: "The action URL"
option :method, desc: 'The action HTTP method' option :method, desc: "The action HTTP method"
def call(first:, **options) def call(first:, **options)
puts "first: #{first}" puts "first: #{first}"
puts "url: #{options[:url]}" puts "url: #{options[:url]}"
puts "method: #{options[:method]}" puts "method: #{options[:method]}"
puts "Unused Arguments: #{options[:args].join(', ')}" puts "Unused Arguments: #{options[:args].join(", ")}"
end end
end end
class OptionsWithAliases < Dry::CLI::Command class OptionsWithAliases < Dry::CLI::Command
desc 'Accepts options with aliases' desc "Accepts options with aliases"
option :url, desc: 'The action URL', aliases: %w[-u u --u] option :url, desc: "The action URL", aliases: %w[-u u --u]
option :flag, desc: 'The flag', type: :boolean, aliases: %w[f] option :flag, desc: "The flag", type: :boolean, aliases: %w[f]
option :opt, desc: 'The opt', type: :boolean, aliases: %w[o], default: false option :opt, desc: "The opt", type: :boolean, aliases: %w[o], default: false
def call(**options) def call(**options)
puts "options with aliases - #{options.inspect}" puts "options with aliases - #{options.inspect}"
@ -404,9 +404,9 @@ module Commands
end end
class RootCommand < Dry::CLI::Command class RootCommand < Dry::CLI::Command
desc 'Root command with arguments and subcommands' desc "Root command with arguments and subcommands"
argument :root_command_argument, desc: 'Root command argument', required: true argument :root_command_argument, desc: "Root command argument", required: true
option :root_command_option, desc: 'Root command option' option :root_command_option, desc: "Root command option"
def call(**params) def call(**params)
puts "I'm a root-command argument:#{params[:root_command_argument]}" puts "I'm a root-command argument:#{params[:root_command_argument]}"
@ -416,9 +416,9 @@ module Commands
module RootCommands module RootCommands
class SubCommand < Dry::CLI::Command class SubCommand < Dry::CLI::Command
desc 'Root command sub command' desc "Root command sub command"
argument :root_command_sub_command_argument, desc: 'Root command sub command argument', required: true argument :root_command_sub_command_argument, desc: "Root command sub command argument", required: true
option :root_command_sub_command_option, desc: 'Root command sub command option' option :root_command_sub_command_option, desc: "Root command sub command option"
def call(**params) def call(**params)
puts "I'm a root-command sub-command argument:#{params[:root_command_sub_command_argument]}" puts "I'm a root-command sub-command argument:#{params[:root_command_sub_command_argument]}"
@ -427,9 +427,9 @@ module Commands
end end
class SubCommand2 < Dry::CLI::Command class SubCommand2 < Dry::CLI::Command
desc 'Root command sub command' desc "Root command sub command"
argument :root_command_sub_command_argument, desc: 'Root command sub command argument', required: true argument :root_command_sub_command_argument, desc: "Root command sub command argument", required: true
option :root_command_sub_command_option, desc: 'Root command sub command option' option :root_command_sub_command_option, desc: "Root command sub command option"
def call(**params) def call(**params)
puts "I'm a root-command sub-command argument:#{params[:root_command_sub_command_argument]}" puts "I'm a root-command sub-command argument:#{params[:root_command_sub_command_argument]}"
@ -454,9 +454,9 @@ end
module Webpack module Webpack
module CLI module CLI
class Generate < Dry::CLI::Command class Generate < Dry::CLI::Command
desc 'Generate webpack configuration' desc "Generate webpack configuration"
option :apps, desc: 'Generate webpack apps', type: :array option :apps, desc: "Generate webpack apps", type: :array
def call(apps: [], **) def call(apps: [], **)
puts "generate webpack. Apps: #{apps}" puts "generate webpack. Apps: #{apps}"
@ -464,23 +464,23 @@ module Webpack
end end
class Hello < Dry::CLI::Command class Hello < Dry::CLI::Command
desc 'Print a greeting' desc "Print a greeting"
def call(*) def call(*)
puts 'hello from webpack' puts "hello from webpack"
end end
end end
class SubCommand < Dry::CLI::Command class SubCommand < Dry::CLI::Command
desc 'Override a subcommand' desc "Override a subcommand"
def call(**) def call(**)
puts 'override from webpack' puts "override from webpack"
end end
end end
class CallbacksCommand < Dry::CLI::Command class CallbacksCommand < Dry::CLI::Command
desc 'Command with callbacks' desc "Command with callbacks"
argument :dir, required: true argument :dir, required: true
option :url option :url

View File

@ -1,79 +1,79 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# frozen_string_literal: true # frozen_string_literal: true
$LOAD_PATH.unshift __dir__ + '/../../lib' $LOAD_PATH.unshift __dir__ + "/../../lib"
require 'dry/cli' require "dry/cli"
require_relative 'shared_commands' require_relative "shared_commands"
WithBlock = Dry::CLI.new do |cli| WithBlock = Dry::CLI.new do |cli|
cli.register 'assets precompile', Commands::Assets::Precompile cli.register "assets precompile", Commands::Assets::Precompile
cli.register 'console', Commands::Console cli.register "console", Commands::Console
cli.register 'new', Commands::New cli.register "new", Commands::New
cli.register 'routes', Commands::Routes cli.register "routes", Commands::Routes
cli.register 'server', Commands::Server, aliases: ['s'] cli.register "server", Commands::Server, aliases: ["s"]
cli.register 'version', Commands::Version, aliases: ['v', '-v', '--version'] cli.register "version", Commands::Version, aliases: ["v", "-v", "--version"]
cli.register 'exec', Commands::Exec cli.register "exec", Commands::Exec
cli.register 'hello', Commands::Hello cli.register "hello", Commands::Hello
cli.register 'greeting', Commands::Greeting cli.register "greeting", Commands::Greeting
cli.register 'sub command', Commands::Sub::Command cli.register "sub command", Commands::Sub::Command
cli.register 'with-initializer', Commands::InitializedCommand.new(prop: 'prop_val') cli.register "with-initializer", Commands::InitializedCommand.new(prop: "prop_val")
cli.register 'root-command', Commands::RootCommand do |prefix| cli.register "root-command", Commands::RootCommand do |prefix|
prefix.register 'sub-command', Commands::RootCommands::SubCommand prefix.register "sub-command", Commands::RootCommands::SubCommand
end end
cli.register 'options-with-aliases', Commands::OptionsWithAliases cli.register "options-with-aliases", Commands::OptionsWithAliases
cli.register 'variadic default', Commands::VariadicArguments cli.register "variadic default", Commands::VariadicArguments
cli.register 'variadic with-mandatory', Commands::MandatoryAndVariadicArguments cli.register "variadic with-mandatory", Commands::MandatoryAndVariadicArguments
cli.register 'variadic with-mandatory-and-options', Commands::MandatoryOptionsAndVariadicArguments cli.register "variadic with-mandatory-and-options", Commands::MandatoryOptionsAndVariadicArguments
cli.register 'generate webpack', Webpack::CLI::Generate cli.register "generate webpack", Webpack::CLI::Generate
cli.register 'hello', Webpack::CLI::Hello cli.register "hello", Webpack::CLI::Hello
cli.register 'sub command', Webpack::CLI::SubCommand cli.register "sub command", Webpack::CLI::SubCommand
cli.register 'callbacks', Webpack::CLI::CallbacksCommand cli.register "callbacks", Webpack::CLI::CallbacksCommand
cli.register 'db' do |prefix| cli.register "db" do |prefix|
prefix.register 'apply', Commands::DB::Apply prefix.register "apply", Commands::DB::Apply
prefix.register 'console', Commands::DB::Console prefix.register "console", Commands::DB::Console
prefix.register 'create', Commands::DB::Create prefix.register "create", Commands::DB::Create
prefix.register 'drop', Commands::DB::Drop prefix.register "drop", Commands::DB::Drop
prefix.register 'migrate', Commands::DB::Migrate prefix.register "migrate", Commands::DB::Migrate
prefix.register 'prepare', Commands::DB::Prepare prefix.register "prepare", Commands::DB::Prepare
prefix.register 'version', Commands::DB::Version prefix.register "version", Commands::DB::Version
prefix.register 'rollback', Commands::DB::Rollback prefix.register "rollback", Commands::DB::Rollback
end end
cli.register 'destroy', aliases: ['d'] do |prefix| cli.register "destroy", aliases: ["d"] do |prefix|
prefix.register 'action', Commands::Destroy::Action prefix.register "action", Commands::Destroy::Action
prefix.register 'app', Commands::Destroy::App prefix.register "app", Commands::Destroy::App
prefix.register 'mailer', Commands::Destroy::Mailer prefix.register "mailer", Commands::Destroy::Mailer
prefix.register 'migration', Commands::Destroy::Migration prefix.register "migration", Commands::Destroy::Migration
prefix.register 'model', Commands::Destroy::Model prefix.register "model", Commands::Destroy::Model
end end
cli.register 'generate', aliases: ['g'] do |prefix| cli.register "generate", aliases: ["g"] do |prefix|
prefix.register 'action', Commands::Generate::Action prefix.register "action", Commands::Generate::Action
prefix.register 'app', Commands::Generate::App prefix.register "app", Commands::Generate::App
prefix.register 'mailer', Commands::Generate::Mailer prefix.register "mailer", Commands::Generate::Mailer
prefix.register 'migration', Commands::Generate::Migration prefix.register "migration", Commands::Generate::Migration
prefix.register 'model', Commands::Generate::Model prefix.register "model", Commands::Generate::Model
prefix.register 'secret', Commands::Generate::Secret prefix.register "secret", Commands::Generate::Secret
end end
# we need to be sure that command will not override with nil command # we need to be sure that command will not override with nil command
cli.register 'generate webpack', nil cli.register "generate webpack", nil
cli.before('callbacks') do |args| cli.before("callbacks") do |args|
puts "before command callback #{self.class.name} #{args.inspect}" puts "before command callback #{self.class.name} #{args.inspect}"
end end
cli.after('callbacks') do |args| cli.after("callbacks") do |args|
puts "after command callback #{self.class.name} #{args.inspect}" puts "after command callback #{self.class.name} #{args.inspect}"
end end
cli.before 'callbacks', Callbacks::BeforeClass cli.before "callbacks", Callbacks::BeforeClass
cli.after 'callbacks', Callbacks::AfterClass cli.after "callbacks", Callbacks::AfterClass
cli.before 'callbacks', Callbacks::Before.new cli.before "callbacks", Callbacks::Before.new
cli.after 'callbacks', Callbacks::After.new cli.after "callbacks", Callbacks::After.new
end end

View File

@ -1,81 +1,81 @@
# frozen_string_literal: true # frozen_string_literal: true
$LOAD_PATH.unshift __dir__ + '/../../lib' $LOAD_PATH.unshift __dir__ + "/../../lib"
require 'dry/cli' require "dry/cli"
require_relative 'shared_commands' require_relative "shared_commands"
module Foo module Foo
module CLI module CLI
module Commands module Commands
extend Dry::CLI::Registry extend Dry::CLI::Registry
register 'assets precompile', ::Commands::Assets::Precompile register "assets precompile", ::Commands::Assets::Precompile
register 'console', ::Commands::Console register "console", ::Commands::Console
register 'db' do |prefix| register "db" do |prefix|
prefix.register 'apply', ::Commands::DB::Apply prefix.register "apply", ::Commands::DB::Apply
prefix.register 'console', ::Commands::DB::Console prefix.register "console", ::Commands::DB::Console
prefix.register 'create', ::Commands::DB::Create prefix.register "create", ::Commands::DB::Create
prefix.register 'drop', ::Commands::DB::Drop prefix.register "drop", ::Commands::DB::Drop
prefix.register 'migrate', ::Commands::DB::Migrate prefix.register "migrate", ::Commands::DB::Migrate
prefix.register 'prepare', ::Commands::DB::Prepare prefix.register "prepare", ::Commands::DB::Prepare
prefix.register 'version', ::Commands::DB::Version prefix.register "version", ::Commands::DB::Version
prefix.register 'rollback', ::Commands::DB::Rollback prefix.register "rollback", ::Commands::DB::Rollback
end end
register 'destroy', aliases: ['d'] do |prefix| register "destroy", aliases: ["d"] do |prefix|
prefix.register 'action', ::Commands::Destroy::Action prefix.register "action", ::Commands::Destroy::Action
prefix.register 'app', ::Commands::Destroy::App prefix.register "app", ::Commands::Destroy::App
prefix.register 'mailer', ::Commands::Destroy::Mailer prefix.register "mailer", ::Commands::Destroy::Mailer
prefix.register 'migration', ::Commands::Destroy::Migration prefix.register "migration", ::Commands::Destroy::Migration
prefix.register 'model', ::Commands::Destroy::Model prefix.register "model", ::Commands::Destroy::Model
end end
register 'generate', aliases: ['g'] do |prefix| register "generate", aliases: ["g"] do |prefix|
prefix.register 'action', ::Commands::Generate::Action prefix.register "action", ::Commands::Generate::Action
prefix.register 'app', ::Commands::Generate::App prefix.register "app", ::Commands::Generate::App
prefix.register 'mailer', ::Commands::Generate::Mailer prefix.register "mailer", ::Commands::Generate::Mailer
prefix.register 'migration', ::Commands::Generate::Migration prefix.register "migration", ::Commands::Generate::Migration
prefix.register 'model', ::Commands::Generate::Model prefix.register "model", ::Commands::Generate::Model
prefix.register 'secret', ::Commands::Generate::Secret prefix.register "secret", ::Commands::Generate::Secret
end end
register 'new', ::Commands::New register "new", ::Commands::New
register 'routes', ::Commands::Routes register "routes", ::Commands::Routes
register 'server', ::Commands::Server, aliases: ['s'] register "server", ::Commands::Server, aliases: ["s"]
register 'version', ::Commands::Version, aliases: ['v', '-v', '--version'] register "version", ::Commands::Version, aliases: ["v", "-v", "--version"]
register 'exec', ::Commands::Exec register "exec", ::Commands::Exec
register 'hello', ::Commands::Hello register "hello", ::Commands::Hello
register 'greeting', ::Commands::Greeting register "greeting", ::Commands::Greeting
register 'sub command', ::Commands::Sub::Command register "sub command", ::Commands::Sub::Command
register 'with-initializer', ::Commands::InitializedCommand.new(prop: 'prop_val') register "with-initializer", ::Commands::InitializedCommand.new(prop: "prop_val")
register 'root-command', ::Commands::RootCommand register "root-command", ::Commands::RootCommand
register 'root-command sub-command', ::Commands::RootCommands::SubCommand register "root-command sub-command", ::Commands::RootCommands::SubCommand
register 'options-with-aliases', ::Commands::OptionsWithAliases register "options-with-aliases", ::Commands::OptionsWithAliases
register 'variadic default', ::Commands::VariadicArguments register "variadic default", ::Commands::VariadicArguments
register 'variadic with-mandatory', ::Commands::MandatoryAndVariadicArguments # rubocop:disable Metrics/LineLength register "variadic with-mandatory", ::Commands::MandatoryAndVariadicArguments
register 'variadic with-mandatory-and-options', ::Commands::MandatoryOptionsAndVariadicArguments # rubocop:disable Metrics/LineLength register "variadic with-mandatory-and-options", ::Commands::MandatoryOptionsAndVariadicArguments # rubocop:disable Metrics/LineLength
register 'generate webpack', ::Webpack::CLI::Generate register "generate webpack", ::Webpack::CLI::Generate
register 'hello', ::Webpack::CLI::Hello register "hello", ::Webpack::CLI::Hello
register 'sub command', ::Webpack::CLI::SubCommand register "sub command", ::Webpack::CLI::SubCommand
register 'callbacks', ::Webpack::CLI::CallbacksCommand register "callbacks", ::Webpack::CLI::CallbacksCommand
register 'generate webpack', nil register "generate webpack", nil
before('callbacks') do |args| before("callbacks") do |args|
puts "before command callback #{self.class.name} #{args.inspect}" puts "before command callback #{self.class.name} #{args.inspect}"
end end
after('callbacks') do |args| after("callbacks") do |args|
puts "after command callback #{self.class.name} #{args.inspect}" puts "after command callback #{self.class.name} #{args.inspect}"
end end
before('callbacks', ::Callbacks::BeforeClass) before("callbacks", ::Callbacks::BeforeClass)
after('callbacks', ::Callbacks::AfterClass) after("callbacks", ::Callbacks::AfterClass)
before('callbacks', ::Callbacks::Before.new) before("callbacks", ::Callbacks::Before.new)
after('callbacks', ::Callbacks::After.new) after("callbacks", ::Callbacks::After.new)
end end
end end
end end

View File

@ -1,80 +1,80 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# frozen_string_literal: true # frozen_string_literal: true
$LOAD_PATH.unshift __dir__ + '/../../lib' $LOAD_PATH.unshift __dir__ + "/../../lib"
require 'dry/cli' require "dry/cli"
require_relative 'shared_commands' require_relative "shared_commands"
WithZeroArityBlock = Dry.CLI do WithZeroArityBlock = Dry.CLI do
register 'assets precompile', Commands::Assets::Precompile register "assets precompile", Commands::Assets::Precompile
register 'console', Commands::Console register "console", Commands::Console
register 'new', Commands::New register "new", Commands::New
register 'routes', Commands::Routes register "routes", Commands::Routes
register 'server', Commands::Server, aliases: ['s'] register "server", Commands::Server, aliases: ["s"]
register 'version', Commands::Version, aliases: ['v', '-v', '--version'] register "version", Commands::Version, aliases: ["v", "-v", "--version"]
register 'exec', Commands::Exec register "exec", Commands::Exec
register 'hello', Commands::Hello register "hello", Commands::Hello
register 'greeting', Commands::Greeting register "greeting", Commands::Greeting
register 'sub command', Commands::Sub::Command register "sub command", Commands::Sub::Command
register 'with-initializer', Commands::InitializedCommand.new(prop: 'prop_val') register "with-initializer", Commands::InitializedCommand.new(prop: "prop_val")
register 'root-command', Commands::RootCommand register "root-command", Commands::RootCommand
register 'root-command' do register "root-command" do
register 'sub-command', Commands::RootCommands::SubCommand register "sub-command", Commands::RootCommands::SubCommand
end end
register 'options-with-aliases', Commands::OptionsWithAliases register "options-with-aliases", Commands::OptionsWithAliases
register 'variadic default', Commands::VariadicArguments register "variadic default", Commands::VariadicArguments
register 'variadic with-mandatory', Commands::MandatoryAndVariadicArguments register "variadic with-mandatory", Commands::MandatoryAndVariadicArguments
register 'variadic with-mandatory-and-options', Commands::MandatoryOptionsAndVariadicArguments register "variadic with-mandatory-and-options", Commands::MandatoryOptionsAndVariadicArguments
register 'generate webpack', Webpack::CLI::Generate register "generate webpack", Webpack::CLI::Generate
register 'hello', Webpack::CLI::Hello register "hello", Webpack::CLI::Hello
register 'sub command', Webpack::CLI::SubCommand register "sub command", Webpack::CLI::SubCommand
register 'callbacks', Webpack::CLI::CallbacksCommand register "callbacks", Webpack::CLI::CallbacksCommand
register 'db' do register "db" do
register 'apply', Commands::DB::Apply register "apply", Commands::DB::Apply
register 'console', Commands::DB::Console register "console", Commands::DB::Console
register 'create', Commands::DB::Create register "create", Commands::DB::Create
register 'drop', Commands::DB::Drop register "drop", Commands::DB::Drop
register 'migrate', Commands::DB::Migrate register "migrate", Commands::DB::Migrate
register 'prepare', Commands::DB::Prepare register "prepare", Commands::DB::Prepare
register 'version', Commands::DB::Version register "version", Commands::DB::Version
register 'rollback', Commands::DB::Rollback register "rollback", Commands::DB::Rollback
end end
register 'destroy', aliases: ['d'] do register "destroy", aliases: ["d"] do
register 'action', Commands::Destroy::Action register "action", Commands::Destroy::Action
register 'app', Commands::Destroy::App register "app", Commands::Destroy::App
register 'mailer', Commands::Destroy::Mailer register "mailer", Commands::Destroy::Mailer
register 'migration', Commands::Destroy::Migration register "migration", Commands::Destroy::Migration
register 'model', Commands::Destroy::Model register "model", Commands::Destroy::Model
end end
register 'generate', aliases: ['g'] do register "generate", aliases: ["g"] do
register 'action', Commands::Generate::Action register "action", Commands::Generate::Action
register 'app', Commands::Generate::App register "app", Commands::Generate::App
register 'mailer', Commands::Generate::Mailer register "mailer", Commands::Generate::Mailer
register 'migration', Commands::Generate::Migration register "migration", Commands::Generate::Migration
register 'model', Commands::Generate::Model register "model", Commands::Generate::Model
register 'secret', Commands::Generate::Secret register "secret", Commands::Generate::Secret
end end
# we need to be sure that command will not override with nil command # we need to be sure that command will not override with nil command
register 'generate webpack', nil register "generate webpack", nil
before('callbacks') do |args| before("callbacks") do |args|
puts "before command callback #{self.class.name} #{args.inspect}" puts "before command callback #{self.class.name} #{args.inspect}"
end end
after('callbacks') do |args| after("callbacks") do |args|
puts "after command callback #{self.class.name} #{args.inspect}" puts "after command callback #{self.class.name} #{args.inspect}"
end end
before 'callbacks', Callbacks::BeforeClass before "callbacks", Callbacks::BeforeClass
after 'callbacks', Callbacks::AfterClass after "callbacks", Callbacks::AfterClass
before 'callbacks', Callbacks::Before.new before "callbacks", Callbacks::Before.new
after 'callbacks', Callbacks::After.new after "callbacks", Callbacks::After.new
end end

View File

@ -4,7 +4,7 @@ module RSpec
module Support module Support
module Helpers module Helpers
def capture_output def capture_output
require 'stringio' require "stringio"
output = StringIO.new output = StringIO.new
original_stdout = $stdout original_stdout = $stdout
$stdout = output $stdout = output
@ -17,7 +17,7 @@ module RSpec
end end
def capture_error def capture_error
require 'stringio' require "stringio"
error = StringIO.new error = StringIO.new
original_stderr = $stderr original_stderr = $stderr
$stderr = error $stderr = error

View File

@ -6,12 +6,12 @@ module RSpec
def self.included(base) def self.included(base)
base.class_eval do base.class_eval do
before do before do
@original_path = ENV['PATH'] @original_path = ENV["PATH"]
ENV['PATH'] = __dir__ + '/fixtures:' + ENV['PATH'] ENV["PATH"] = __dir__ + "/fixtures:" + ENV["PATH"]
end end
after do after do
ENV['PATH'] = @original_path ENV["PATH"] = @original_path
end end
end end
end end

View File

@ -17,7 +17,7 @@ RSpec.configure do |config|
config.warnings = true config.warnings = true
config.default_formatter = 'doc' if config.files_to_run.one? config.default_formatter = "doc" if config.files_to_run.one?
config.profile_examples = 10 config.profile_examples = 10
config.order = :random config.order = :random

View File

@ -1,49 +1,49 @@
# frozen_string_literal: true # frozen_string_literal: true
# rubocop:disable Metrics/LineLength # rubocop:disable Metrics/LineLength
RSpec.shared_examples 'Commands' do |cli| RSpec.shared_examples "Commands" do |cli|
let(:cli) { cli } let(:cli) { cli }
let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) } let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) }
it 'calls basic command' do it "calls basic command" do
output = capture_output { cli.call(arguments: ['version']) } output = capture_output { cli.call(arguments: ["version"]) }
expect(output).to eq("v1.0.0\n") expect(output).to eq("v1.0.0\n")
end end
it 'calls basic command with alias' do it "calls basic command with alias" do
output = capture_output { cli.call(arguments: ['v']) } output = capture_output { cli.call(arguments: ["v"]) }
expect(output).to eq("v1.0.0\n") expect(output).to eq("v1.0.0\n")
output = capture_output { cli.call(arguments: ['-v']) } output = capture_output { cli.call(arguments: ["-v"]) }
expect(output).to eq("v1.0.0\n") expect(output).to eq("v1.0.0\n")
output = capture_output { cli.call(arguments: ['--version']) } output = capture_output { cli.call(arguments: ["--version"]) }
expect(output).to eq("v1.0.0\n") expect(output).to eq("v1.0.0\n")
end end
it 'calls subcommand via intermediate alias' do it "calls subcommand via intermediate alias" do
output = capture_output { cli.call(arguments: %w[g secret web]) } output = capture_output { cli.call(arguments: %w[g secret web]) }
expect(output).to eq("generate secret - app: web\n") expect(output).to eq("generate secret - app: web\n")
end end
context 'works with params' do context "works with params" do
it 'without params' do it "without params" do
output = capture_output { cli.call(arguments: ['server']) } output = capture_output { cli.call(arguments: ["server"]) }
expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"]}\n") expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"]}\n")
end end
it 'a param using space' do it "a param using space" do
output = capture_output { cli.call(arguments: %w[server --server thin]) } output = capture_output { cli.call(arguments: %w[server --server thin]) }
expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :server=>\"thin\"}\n") expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :server=>\"thin\"}\n")
end end
it 'a param using equal sign' do it "a param using equal sign" do
output = capture_output { cli.call(arguments: %w[server --host=localhost]) } output = capture_output { cli.call(arguments: %w[server --host=localhost]) }
expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :host=>\"localhost\"}\n") expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :host=>\"localhost\"}\n")
end end
it 'a param using alias' do it "a param using alias" do
output = capture_output { cli.call(arguments: %w[options-with-aliases -u test]) } output = capture_output { cli.call(arguments: %w[options-with-aliases -u test]) }
expect(output).to eq("options with aliases - {:opt=>false, :url=>\"test\"}\n") expect(output).to eq("options with aliases - {:opt=>false, :url=>\"test\"}\n")
@ -60,48 +60,48 @@ RSpec.shared_examples 'Commands' do |cli|
expect(output).to eq("options with aliases - {:opt=>true, :flag=>true}\n") expect(output).to eq("options with aliases - {:opt=>true, :flag=>true}\n")
end end
it 'a param with unknown param' do it "a param with unknown param" do
error = capture_error { cli.call(arguments: %w[server --unknown 1234]) } error = capture_error { cli.call(arguments: %w[server --unknown 1234]) }
expect(error).to eq("ERROR: \"rspec server\" was called with arguments \"--unknown 1234\"\n") expect(error).to eq("ERROR: \"rspec server\" was called with arguments \"--unknown 1234\"\n")
end end
it 'with boolean param' do it "with boolean param" do
output = capture_output { cli.call(arguments: ['server']) } output = capture_output { cli.call(arguments: ["server"]) }
expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"]}\n") expect(output).to eq("server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"]}\n")
output = capture_output { cli.call(arguments: %w[server --no-code-reloading]) } output = capture_output { cli.call(arguments: %w[server --no-code-reloading]) }
expect(output).to eq("server - {:code_reloading=>false, :deps=>[\"dep1\", \"dep2\"]}\n") expect(output).to eq("server - {:code_reloading=>false, :deps=>[\"dep1\", \"dep2\"]}\n")
end end
context 'with array param' do context "with array param" do
it 'allows to omit optional array argument' do it "allows to omit optional array argument" do
output = capture_output { cli.call(arguments: %w[exec test]) } output = capture_output { cli.call(arguments: %w[exec test]) }
expect(output).to eq("exec - Task: test - Directories: []\n") expect(output).to eq("exec - Task: test - Directories: []\n")
end end
it 'capture all the remaining arguments' do it "capture all the remaining arguments" do
output = capture_output { cli.call(arguments: %w[exec test api admin]) } output = capture_output { cli.call(arguments: %w[exec test api admin]) }
expect(output).to eq("exec - Task: test - Directories: [\"api\", \"admin\"]\n") expect(output).to eq("exec - Task: test - Directories: [\"api\", \"admin\"]\n")
end end
end end
context 'with supported values' do context "with supported values" do
context 'and with supported value passed' do context "and with supported value passed" do
it 'call the command with the option' do it "call the command with the option" do
output = capture_output { cli.call(arguments: %w[console --engine=pry]) } output = capture_output { cli.call(arguments: %w[console --engine=pry]) }
expect(output).to eq("console - engine: pry\n") expect(output).to eq("console - engine: pry\n")
end end
end end
context 'and with an unknown value passed' do context "and with an unknown value passed" do
it 'prints error' do it "prints error" do
error = capture_error { cli.call(arguments: %w[console --engine=unknown]) } error = capture_error { cli.call(arguments: %w[console --engine=unknown]) }
expect(error).to eq("ERROR: \"rspec console\" was called with arguments \"--engine=unknown\"\n") # rubocop:disable Metrics/LineLength expect(error).to eq("ERROR: \"rspec console\" was called with arguments \"--engine=unknown\"\n") # rubocop:disable Metrics/LineLength
end end
end end
end end
it 'with help param' do it "with help param" do
output = capture_output { cli.call(arguments: %w[server --help]) } output = capture_output { cli.call(arguments: %w[server --help]) }
expected = <<~DESC expected = <<~DESC
@ -137,18 +137,18 @@ RSpec.shared_examples 'Commands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
context 'with required params' do context "with required params" do
it 'can be used' do it "can be used" do
output = capture_output { cli.call(arguments: %w[new bookshelf]) } output = capture_output { cli.call(arguments: %w[new bookshelf]) }
expect(output).to eq("new - project: bookshelf\n") expect(output).to eq("new - project: bookshelf\n")
end end
it 'with unknown param' do it "with unknown param" do
error = capture_error { cli.call(arguments: %w[new bookshelf --unknown 1234]) } error = capture_error { cli.call(arguments: %w[new bookshelf --unknown 1234]) }
expect(error).to eq("ERROR: \"rspec new\" was called with arguments \"bookshelf --unknown 1234\"\n") # rubocop:disable Metrics/LineLength expect(error).to eq("ERROR: \"rspec new\" was called with arguments \"bookshelf --unknown 1234\"\n") # rubocop:disable Metrics/LineLength
end end
it 'no required' do it "no required" do
output = capture_output { cli.call(arguments: %w[generate secret web]) } output = capture_output { cli.call(arguments: %w[generate secret web]) }
expect(output).to eq("generate secret - app: web\n") expect(output).to eq("generate secret - app: web\n")
@ -157,7 +157,7 @@ RSpec.shared_examples 'Commands' do |cli|
end end
it "an error is displayed if there aren't required params" do it "an error is displayed if there aren't required params" do
error = capture_error { cli.call(arguments: ['new']) } error = capture_error { cli.call(arguments: ["new"]) }
expected_error = <<~DESC expected_error = <<~DESC
ERROR: "#{cmd} new" was called with no arguments ERROR: "#{cmd} new" was called with no arguments
Usage: "#{cmd} new PROJECT" Usage: "#{cmd} new PROJECT"
@ -165,7 +165,7 @@ RSpec.shared_examples 'Commands' do |cli|
expect(error).to eq(expected_error) expect(error).to eq(expected_error)
end end
it 'with default value and using options' do it "with default value and using options" do
output = capture_output { cli.call(arguments: %w[greeting --person=Alfonso]) } output = capture_output { cli.call(arguments: %w[greeting --person=Alfonso]) }
expect(output).to eq("response: Hello World, person: Alfonso\n") expect(output).to eq("response: Hello World, person: Alfonso\n")
@ -174,24 +174,24 @@ RSpec.shared_examples 'Commands' do |cli|
end end
end end
context 'with extra params' do context "with extra params" do
it 'is accessible via options[:args]' do it "is accessible via options[:args]" do
output = capture_output { cli.call(arguments: %w[variadic default bar baz]) } output = capture_output { cli.call(arguments: %w[variadic default bar baz]) }
expect(output).to eq("Unused Arguments: bar, baz\n") expect(output).to eq("Unused Arguments: bar, baz\n")
end end
context 'when there is a required argument' do context "when there is a required argument" do
it 'parses both separately' do it "parses both separately" do
output = capture_output { cli.call(arguments: ['variadic', 'with-mandatory', cmd, 'bar', 'baz']) } output = capture_output { cli.call(arguments: ["variadic", "with-mandatory", cmd, "bar", "baz"]) }
expect(output).to eq("first: #{cmd}\nUnused Arguments: bar, baz\n") expect(output).to eq("first: #{cmd}\nUnused Arguments: bar, baz\n")
end end
context 'and there are options' do context "and there are options" do
it 'parses both separately' do it "parses both separately" do
output = capture_output { cli.call(arguments: ['variadic', 'with-mandatory-and-options', cmd, 'bar', 'baz']) } output = capture_output { cli.call(arguments: ["variadic", "with-mandatory-and-options", cmd, "bar", "baz"]) }
expect(output).to eq("first: #{cmd}\nurl: \nmethod: \nUnused Arguments: bar, baz\n") expect(output).to eq("first: #{cmd}\nurl: \nmethod: \nUnused Arguments: bar, baz\n")
output = capture_output { cli.call(arguments: ['variadic', 'with-mandatory-and-options', '--url=root', '--method=index', cmd, 'bar', 'baz']) } output = capture_output { cli.call(arguments: ["variadic", "with-mandatory-and-options", "--url=root", "--method=index", cmd, "bar", "baz"]) }
expect(output).to eq("first: #{cmd}\nurl: root\nmethod: index\nUnused Arguments: bar, baz\n") expect(output).to eq("first: #{cmd}\nurl: root\nmethod: index\nUnused Arguments: bar, baz\n")
output = capture_output { cli.call(arguments: %w[variadic with-mandatory-and-options uno -- due tre --blah]) } output = capture_output { cli.call(arguments: %w[variadic with-mandatory-and-options uno -- due tre --blah]) }
@ -202,8 +202,8 @@ RSpec.shared_examples 'Commands' do |cli|
end end
end end
context 'works with command with arguments and subcommands' do context "works with command with arguments and subcommands" do
it 'shows help' do it "shows help" do
output = capture_output { cli.call(arguments: %w[root-command -h]) } output = capture_output { cli.call(arguments: %w[root-command -h]) }
expected = <<~DESC expected = <<~DESC
Command: Command:
@ -232,8 +232,8 @@ RSpec.shared_examples 'Commands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
context 'works with params' do context "works with params" do
it 'without params' do it "without params" do
error = capture_error { cli.call(arguments: %w[root-command]) } error = capture_error { cli.call(arguments: %w[root-command]) }
expected = <<~DESC expected = <<~DESC
ERROR: "rspec root-command" was called with no arguments ERROR: "rspec root-command" was called with no arguments
@ -243,9 +243,9 @@ RSpec.shared_examples 'Commands' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'with params' do it "with params" do
output = capture_output { output = capture_output {
cli.call(arguments: ['root-command', '"hello world"']) cli.call(arguments: ["root-command", '"hello world"'])
} }
expected = <<~DESC expected = <<~DESC
I'm a root-command argument:"hello world" I'm a root-command argument:"hello world"
@ -255,12 +255,12 @@ RSpec.shared_examples 'Commands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
it 'with option using space' do it "with option using space" do
output = capture_output { output = capture_output {
cli.call(arguments: [ cli.call(arguments: [
'root-command', "root-command",
'"hello world"', '"hello world"',
'--root-command-option', "--root-command-option",
'"bye world"' '"bye world"'
]) ])
} }
@ -272,10 +272,10 @@ RSpec.shared_examples 'Commands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
it 'with option using equal sign' do it "with option using equal sign" do
output = capture_output { output = capture_output {
cli.call(arguments: [ cli.call(arguments: [
'root-command', "root-command",
'"hello world"', '"hello world"',
'--root-command-option="bye world"' '--root-command-option="bye world"'
]) ])
@ -290,8 +290,8 @@ RSpec.shared_examples 'Commands' do |cli|
end end
end end
context 'works with instances of commands' do context "works with instances of commands" do
it 'executes instance' do it "executes instance" do
output = capture_output { cli.call(arguments: %w[with-initializer]) } output = capture_output { cli.call(arguments: %w[with-initializer]) }
expect(output).to eq("The value of prop is prop_val\n") expect(output).to eq("The value of prop is prop_val\n")
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'Rendering' do |cli| RSpec.shared_examples "Rendering" do |cli|
let(:cli) { cli } let(:cli) { cli }
let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) } let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) }
it 'prints required params' do it "prints required params" do
error = capture_error { cli.call } error = capture_error { cli.call }
expected = <<~DESC expected = <<~DESC
Commands: Commands:
@ -32,8 +32,8 @@ RSpec.shared_examples 'Rendering' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'prints required params with labels' do it "prints required params with labels" do
error = capture_error { cli.call(arguments: ['destroy']) } error = capture_error { cli.call(arguments: ["destroy"]) }
expected = <<~DESC expected = <<~DESC
Commands: Commands:
@ -47,7 +47,7 @@ RSpec.shared_examples 'Rendering' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'prints available commands for unknown subcommand' do it "prints available commands for unknown subcommand" do
error = capture_error { cli.call(arguments: %w[generate unknown]) } error = capture_error { cli.call(arguments: %w[generate unknown]) }
expected = <<~DESC expected = <<~DESC
@ -64,8 +64,8 @@ RSpec.shared_examples 'Rendering' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'prints available commands for unknown command' do it "prints available commands for unknown command" do
error = capture_error { cli.call(arguments: ['unknown']) } error = capture_error { cli.call(arguments: ["unknown"]) }
expected = <<~DESC expected = <<~DESC
Commands: Commands:
@ -92,7 +92,7 @@ RSpec.shared_examples 'Rendering' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'prints first level' do it "prints first level" do
error = capture_error { cli.call } error = capture_error { cli.call }
expected = <<~DESC expected = <<~DESC
@ -121,7 +121,7 @@ RSpec.shared_examples 'Rendering' do |cli|
end end
it "prints subcommand's commands" do it "prints subcommand's commands" do
error = capture_error { cli.call(arguments: ['generate']) } error = capture_error { cli.call(arguments: ["generate"]) }
expected = <<~DESC expected = <<~DESC
Commands: Commands:
@ -153,7 +153,7 @@ RSpec.shared_examples 'Rendering' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'prints list options when calling help' do it "prints list options when calling help" do
output = capture_output { cli.call(arguments: %w[options-with-aliases --help]) } output = capture_output { cli.call(arguments: %w[options-with-aliases --help]) }
expected = <<~DESC expected = <<~DESC

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'Subcommands' do |cli| RSpec.shared_examples "Subcommands" do |cli|
let(:cli) { cli } let(:cli) { cli }
let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) } let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) }
it 'calls subcommand' do it "calls subcommand" do
error = capture_error { cli.call(arguments: %w[generate model]) } error = capture_error { cli.call(arguments: %w[generate model]) }
expected = <<~DESC expected = <<~DESC
ERROR: "#{cmd} generate model" was called with no arguments ERROR: "#{cmd} generate model" was called with no arguments
@ -15,8 +15,8 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
context 'works with params' do context "works with params" do
it 'without params' do it "without params" do
error = capture_error { cli.call(arguments: %w[generate model]) } error = capture_error { cli.call(arguments: %w[generate model]) }
expected = <<~DESC expected = <<~DESC
ERROR: "#{cmd} generate model" was called with no arguments ERROR: "#{cmd} generate model" was called with no arguments
@ -26,28 +26,28 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'a param using space' do it "a param using space" do
output = capture_output { cli.call(arguments: %w[server --port 2306]) } output = capture_output { cli.call(arguments: %w[server --port 2306]) }
expect(output).to eq( expect(output).to eq(
"server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :port=>\"2306\"}\n" "server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :port=>\"2306\"}\n"
) )
end end
it 'a param using equal sign' do it "a param using equal sign" do
output = capture_output { cli.call(arguments: %w[server --port=2306]) } output = capture_output { cli.call(arguments: %w[server --port=2306]) }
expect(output).to eq( expect(output).to eq(
"server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :port=>\"2306\"}\n" "server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :port=>\"2306\"}\n"
) )
end end
it 'a param using alias' do it "a param using alias" do
output = capture_output { cli.call(arguments: %w[server -p 2306]) } output = capture_output { cli.call(arguments: %w[server -p 2306]) }
expect(output).to eq( expect(output).to eq(
"server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :port=>\"2306\"}\n" "server - {:code_reloading=>true, :deps=>[\"dep1\", \"dep2\"], :port=>\"2306\"}\n"
) )
end end
it 'with help param' do it "with help param" do
output = capture_output { cli.call(arguments: %w[generate model --help]) } output = capture_output { cli.call(arguments: %w[generate model --help]) }
expected = <<~DESC expected = <<~DESC
@ -75,28 +75,28 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
context 'with required params' do context "with required params" do
it 'only one param' do it "only one param" do
output = capture_output { cli.call(arguments: %w[generate model user]) } output = capture_output { cli.call(arguments: %w[generate model user]) }
expect(output).to eq("generate model - model: user\n") expect(output).to eq("generate model - model: user\n")
end end
it 'more than one param' do it "more than one param" do
output = capture_output { cli.call(arguments: %w[destroy action web users#index]) } output = capture_output { cli.call(arguments: %w[destroy action web users#index]) }
expect(output).to eq("destroy action - app: web, action: users#index\n") expect(output).to eq("destroy action - app: web, action: users#index\n")
end end
it 'more than one param and with optional params' do it "more than one param and with optional params" do
output = capture_output { cli.call(arguments: %w[generate action web users#index --url=/signin]) } # rubocop:disable Metrics/LineLength output = capture_output { cli.call(arguments: %w[generate action web users#index --url=/signin]) } # rubocop:disable Metrics/LineLength
expect(output).to eq("generate action - app: web, action: users#index, options: {:skip_view=>false, :url=>\"/signin\"}\n") # rubocop:disable Metrics/LineLength expect(output).to eq("generate action - app: web, action: users#index, options: {:skip_view=>false, :url=>\"/signin\"}\n") # rubocop:disable Metrics/LineLength
end end
it 'more than one param and with boolean params' do it "more than one param and with boolean params" do
output = capture_output { cli.call(arguments: %w[generate action web users#index --skip-view --url=/signin]) } # rubocop:disable Metrics/LineLength output = capture_output { cli.call(arguments: %w[generate action web users#index --skip-view --url=/signin]) } # rubocop:disable Metrics/LineLength
expect(output).to eq("generate action - app: web, action: users#index, options: {:skip_view=>true, :url=>\"/signin\"}\n") # rubocop:disable Metrics/LineLength expect(output).to eq("generate action - app: web, action: users#index, options: {:skip_view=>true, :url=>\"/signin\"}\n") # rubocop:disable Metrics/LineLength
end end
it 'more than required params' do it "more than required params" do
output = capture_output { cli.call(arguments: %w[destroy action web users#index unexpected_param]) } # rubocop:disable Metrics/LineLength output = capture_output { cli.call(arguments: %w[destroy action web users#index unexpected_param]) } # rubocop:disable Metrics/LineLength
expect(output).to eq("destroy action - app: web, action: users#index\n") expect(output).to eq("destroy action - app: web, action: users#index\n")
end end
@ -111,7 +111,7 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'an error is displayed if there are some required params' do it "an error is displayed if there are some required params" do
error = capture_error { cli.call(arguments: %w[destroy action web]) } error = capture_error { cli.call(arguments: %w[destroy action web]) }
expected = <<~DESC expected = <<~DESC
ERROR: "#{cmd} destroy action" was called with arguments [\"web\"] ERROR: "#{cmd} destroy action" was called with arguments [\"web\"]
@ -121,14 +121,14 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
context 'and a default value' do context "and a default value" do
it 'returns the default value if nothing is passed' do it "returns the default value if nothing is passed" do
output = capture_output { cli.call(arguments: %w[db rollback]) } output = capture_output { cli.call(arguments: %w[db rollback]) }
expect(output).to eq("1\n") expect(output).to eq("1\n")
end end
it 'returns the passed value' do it "returns the passed value" do
output = capture_output { cli.call(arguments: %w[db rollback 3]) } output = capture_output { cli.call(arguments: %w[db rollback 3]) }
expect(output).to eq("3\n") expect(output).to eq("3\n")
@ -137,8 +137,8 @@ RSpec.shared_examples 'Subcommands' do |cli|
end end
end end
context 'works with root command' do context "works with root command" do
it 'shows help' do it "shows help" do
output = capture_output { cli.call(arguments: %w[root-command sub-command -h]) } output = capture_output { cli.call(arguments: %w[root-command sub-command -h]) }
expected = <<~DESC expected = <<~DESC
Command: Command:
@ -164,8 +164,8 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
context 'works with params' do context "works with params" do
it 'without params' do it "without params" do
error = capture_error { cli.call(arguments: %w[root-command sub-command]) } error = capture_error { cli.call(arguments: %w[root-command sub-command]) }
expected = <<~DESC expected = <<~DESC
ERROR: "rspec root-command sub-command" was called with no arguments ERROR: "rspec root-command sub-command" was called with no arguments
@ -175,9 +175,9 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(error).to eq(expected) expect(error).to eq(expected)
end end
it 'with params' do it "with params" do
output = capture_output { output = capture_output {
cli.call(arguments: ['root-command', 'sub-command', '"hello world"']) cli.call(arguments: ["root-command", "sub-command", '"hello world"'])
} }
expected = <<~DESC expected = <<~DESC
I'm a root-command sub-command argument:"hello world" I'm a root-command sub-command argument:"hello world"
@ -187,13 +187,13 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
it 'with option using space' do it "with option using space" do
output = capture_output { output = capture_output {
cli.call(arguments: [ cli.call(arguments: [
'root-command', "root-command",
'sub-command', "sub-command",
'"hello world"', '"hello world"',
'--root-command-sub-command-option', "--root-command-sub-command-option",
'"bye world"' '"bye world"'
]) ])
} }
@ -205,11 +205,11 @@ RSpec.shared_examples 'Subcommands' do |cli|
expect(output).to eq(expected) expect(output).to eq(expected)
end end
it 'with option using equal sign' do it "with option using equal sign" do
output = capture_output { output = capture_output {
cli.call(arguments: [ cli.call(arguments: [
'root-command', "root-command",
'sub-command', "sub-command",
'"hello world"', '"hello world"',
'--root-command-sub-command-option="bye world"' '--root-command-sub-command-option="bye world"'
]) ])

View File

@ -1,32 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'Third-party gems' do |cli| RSpec.shared_examples "Third-party gems" do |cli|
let(:cli) { cli } let(:cli) { cli }
let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) } let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) }
it 'allows to add a subcommand' do it "allows to add a subcommand" do
output = capture_output { cli.call(arguments: %w[generate webpack]) } output = capture_output { cli.call(arguments: %w[generate webpack]) }
expect(output).to eq("generate webpack. Apps: []\n") expect(output).to eq("generate webpack. Apps: []\n")
end end
it 'allows to invoke a subcommand via an inherited subcomand aliases' do it "allows to invoke a subcommand via an inherited subcomand aliases" do
output = capture_output { cli.call(arguments: %w[g webpack]) } output = capture_output { cli.call(arguments: %w[g webpack]) }
expect(output).to eq("generate webpack. Apps: []\n") expect(output).to eq("generate webpack. Apps: []\n")
end end
it 'allows to override basic commands' do it "allows to override basic commands" do
output = capture_output { cli.call(arguments: ['hello']) } output = capture_output { cli.call(arguments: ["hello"]) }
expect(output).to eq("hello from webpack\n") expect(output).to eq("hello from webpack\n")
end end
it 'allows to override a subcommand' do it "allows to override a subcommand" do
output = capture_output { cli.call(arguments: %w[sub command]) } output = capture_output { cli.call(arguments: %w[sub command]) }
expect(output).to eq("override from webpack\n") expect(output).to eq("override from webpack\n")
end end
context 'callbacks' do context "callbacks" do
it 'allows to add callbacks as a block' do it "allows to add callbacks as a block" do
expected = <<~OUTPUT expected = <<~OUTPUT
before command callback Webpack::CLI::CallbacksCommand {:url=>"https://hanamirb.test", :dir=>"."} before command callback Webpack::CLI::CallbacksCommand {:url=>"https://hanamirb.test", :dir=>"."}
before callback (class), 2 arg(s): {:url=>"https://hanamirb.test", :dir=>"."} before callback (class), 2 arg(s): {:url=>"https://hanamirb.test", :dir=>"."}
@ -42,7 +42,7 @@ RSpec.shared_examples 'Third-party gems' do |cli|
end end
end end
it 'allows to call array option' do it "allows to call array option" do
output = capture_output { cli.call(arguments: %w[generate webpack --apps=test,api,admin]) } output = capture_output { cli.call(arguments: %w[generate webpack --apps=test,api,admin]) }
expect(output).to eq("generate webpack. Apps: [\"test\", \"api\", \"admin\"]\n") expect(output).to eq("generate webpack. Apps: [\"test\", \"api\", \"admin\"]\n")
end end

View File

@ -1,35 +1,35 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe 'CLI' do RSpec.describe "CLI" do
context 'when registry' do context "when registry" do
context 'passing module' do context "passing module" do
include_examples 'Commands', WithRegistry include_examples "Commands", WithRegistry
include_examples 'Rendering', WithRegistry include_examples "Rendering", WithRegistry
include_examples 'Subcommands', WithRegistry include_examples "Subcommands", WithRegistry
include_examples 'Third-party gems', WithRegistry include_examples "Third-party gems", WithRegistry
end end
context 'passing block' do context "passing block" do
include_examples 'Commands', WithBlock include_examples "Commands", WithBlock
include_examples 'Rendering', WithBlock include_examples "Rendering", WithBlock
include_examples 'Subcommands', WithBlock include_examples "Subcommands", WithBlock
include_examples 'Third-party gems', WithBlock include_examples "Third-party gems", WithBlock
end end
context 'passing block with no arguments' do context "passing block with no arguments" do
include_examples 'Commands', WithZeroArityBlock include_examples "Commands", WithZeroArityBlock
include_examples 'Rendering', WithZeroArityBlock include_examples "Rendering", WithZeroArityBlock
include_examples 'Subcommands', WithZeroArityBlock include_examples "Subcommands", WithZeroArityBlock
include_examples 'Third-party gems', WithZeroArityBlock include_examples "Third-party gems", WithZeroArityBlock
end end
end end
context 'with command' do context "with command" do
let(:cli) { Dry.CLI(Baz::CLI) } let(:cli) { Dry.CLI(Baz::CLI) }
let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) } let(:cmd) { File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) }
it 'shows help' do it "shows help" do
output = capture_output { cli.call(arguments: ['-h']) } output = capture_output { cli.call(arguments: ["-h"]) }
expected_output = <<~OUTPUT expected_output = <<~OUTPUT
Command: Command:
#{cmd} #{cmd}
@ -53,90 +53,66 @@ RSpec.describe 'CLI' do
expect(output).to eq(expected_output) expect(output).to eq(expected_output)
end end
it 'with required_argument' do it "with required_argument" do
output = capture_output { cli.call(arguments: ['first_arg']) } output = capture_output { cli.call(arguments: ["first_arg"]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test\"}\n" "Options: {:option_with_default=>\"test\"}\n"
) )
end end
it 'with optional_arg' do it "with optional_arg" do
output = capture_output { cli.call(arguments: %w[first_arg opt_arg]) } output = capture_output { cli.call(arguments: %w[first_arg opt_arg]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: opt_arg. ' \ "mandatory_arg: first_arg. optional_arg: opt_arg. " \
"Options: {:option_with_default=>\"test\", :args=>[\"opt_arg\"]}\n" "Options: {:option_with_default=>\"test\", :args=>[\"opt_arg\"]}\n"
) )
end end
it 'with option_one', if: RUBY_VERSION < '2.4' do it "with underscored option_one" do
output = capture_output { cli.call(arguments: %w[first_arg --option-one=test2]) }
expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \
"Options: {:option_with_default=>\"test\", :option_one=>\"test2\"}\n"
)
end
it 'with underscored option_one', if: RUBY_VERSION >= '2.4' do
output = capture_output { cli.call(arguments: %w[first_arg --option_one=test2]) } output = capture_output { cli.call(arguments: %w[first_arg --option_one=test2]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test\", :option_one=>\"test2\"}\n" "Options: {:option_with_default=>\"test\", :option_one=>\"test2\"}\n"
) )
end end
it 'with option_one alias' do it "with option_one alias" do
output = capture_output { cli.call(arguments: %w[first_arg -1 test2]) } output = capture_output { cli.call(arguments: %w[first_arg -1 test2]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test\", :option_one=>\"test2\"}\n" "Options: {:option_with_default=>\"test\", :option_one=>\"test2\"}\n"
) )
end end
it 'with boolean_option', if: RUBY_VERSION < '2.4' do it "with underscored boolean_option" do
output = capture_output { cli.call(arguments: %w[first_arg --boolean-option]) }
expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \
"Options: {:option_with_default=>\"test\", :boolean_option=>true}\n"
)
end
it 'with underscored boolean_option', if: RUBY_VERSION >= '2.4' do
output = capture_output { cli.call(arguments: %w[first_arg --boolean_option]) } output = capture_output { cli.call(arguments: %w[first_arg --boolean_option]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test\", :boolean_option=>true}\n" "Options: {:option_with_default=>\"test\", :boolean_option=>true}\n"
) )
end end
it 'with boolean_option alias' do it "with boolean_option alias" do
output = capture_output { cli.call(arguments: %w[first_arg -b]) } output = capture_output { cli.call(arguments: %w[first_arg -b]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test\", :boolean_option=>true}\n" "Options: {:option_with_default=>\"test\", :boolean_option=>true}\n"
) )
end end
it 'with option_with_default alias', if: RUBY_VERSION < '2.4' do it "with underscoreed option_with_default alias" do
output = capture_output { cli.call(arguments: %w[first_arg --option-with-default=test3]) }
expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \
"Options: {:option_with_default=>\"test3\"}\n"
)
end
it 'with underscoreed option_with_default alias', if: RUBY_VERSION >= '2.4' do
output = capture_output { cli.call(arguments: %w[first_arg --option_with_default=test3]) } output = capture_output { cli.call(arguments: %w[first_arg --option_with_default=test3]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test3\"}\n" "Options: {:option_with_default=>\"test3\"}\n"
) )
end end
it 'with combination of aliases' do it "with combination of aliases" do
output = capture_output { cli.call(arguments: %w[first_arg -bd test3]) } output = capture_output { cli.call(arguments: %w[first_arg -bd test3]) }
expect(output).to eq( expect(output).to eq(
'mandatory_arg: first_arg. optional_arg: optional_arg. ' \ "mandatory_arg: first_arg. optional_arg: optional_arg. " \
"Options: {:option_with_default=>\"test3\", :boolean_option=>true}\n" "Options: {:option_with_default=>\"test3\", :boolean_option=>true}\n"
) )
end end

View File

@ -1,26 +1,26 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Dry::CLI::Inflector do RSpec.describe Dry::CLI::Inflector do
describe '.dasherize' do describe ".dasherize" do
it 'returns nil if input is nil' do it "returns nil if input is nil" do
expect(described_class.dasherize(nil)).to be(nil) expect(described_class.dasherize(nil)).to be(nil)
end end
it 'downcases input' do it "downcases input" do
expect(described_class.dasherize('Dry')).to eq('dry') expect(described_class.dasherize("Dry")).to eq("dry")
expect(described_class.dasherize('CLI')).to eq('cli') expect(described_class.dasherize("CLI")).to eq("cli")
end end
it 'replaces spaces with dashes' do it "replaces spaces with dashes" do
expect(described_class.dasherize('Command Line Interface')).to eq('command-line-interface') expect(described_class.dasherize("Command Line Interface")).to eq("command-line-interface")
end end
it 'replaces underscores with dashes' do it "replaces underscores with dashes" do
expect(described_class.dasherize('fast_code_reloading')).to eq('fast-code-reloading') expect(described_class.dasherize("fast_code_reloading")).to eq("fast-code-reloading")
end end
it 'accepts any object that respond to #to_s' do it "accepts any object that respond to #to_s" do
expect(described_class.dasherize(:dry)).to eq('dry') expect(described_class.dasherize(:dry)).to eq("dry")
end end
end end
end end

View File

@ -1,11 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe Dry::CLI::Registry do RSpec.describe Dry::CLI::Registry do
describe '.before' do describe ".before" do
context "when command can't be found" do context "when command can't be found" do
it 'raises error' do it "raises error" do
expect do expect do
Bar::CLI::Commands.before('pixel') { puts 'hello' } Bar::CLI::Commands.before("pixel") { puts "hello" }
end.to raise_error( end.to raise_error(
Dry::CLI::UnknownCommandError, Dry::CLI::UnknownCommandError,
"unknown command: `pixel'" "unknown command: `pixel'"
@ -13,12 +13,12 @@ RSpec.describe Dry::CLI::Registry do
end end
end end
context 'when object is given' do context "when object is given" do
it "raises error when it doesn't respond to #call" do it "raises error when it doesn't respond to #call" do
callback = Object.new callback = Object.new
expect do expect do
Bar::CLI::Commands.before('alpha', callback) Bar::CLI::Commands.before("alpha", callback)
end.to raise_error( end.to raise_error(
Dry::CLI::InvalidCallbackError, Dry::CLI::InvalidCallbackError,
"expected `#{callback.inspect}' to respond to `#call'" "expected `#{callback.inspect}' to respond to `#call'"
@ -26,12 +26,12 @@ RSpec.describe Dry::CLI::Registry do
end end
end end
context 'when class is given' do context "when class is given" do
it 'raises error when #initialize arity is not equal to 0' do it "raises error when #initialize arity is not equal to 0" do
callback = Struct callback = Struct
expect do expect do
Bar::CLI::Commands.before('alpha', callback) Bar::CLI::Commands.before("alpha", callback)
end.to raise_error( end.to raise_error(
Dry::CLI::InvalidCallbackError, Dry::CLI::InvalidCallbackError,
"expected `#{callback.inspect}' to respond to `#initialize' with arity 0" "expected `#{callback.inspect}' to respond to `#initialize' with arity 0"
@ -40,21 +40,21 @@ RSpec.describe Dry::CLI::Registry do
end end
end end
describe '.after' do describe ".after" do
context "when command can't be found" do context "when command can't be found" do
it 'raises error' do it "raises error" do
expect do expect do
Bar::CLI::Commands.after('peta') { puts 'hello' } Bar::CLI::Commands.after("peta") { puts "hello" }
end.to raise_error(Dry::CLI::UnknownCommandError, "unknown command: `peta'") end.to raise_error(Dry::CLI::UnknownCommandError, "unknown command: `peta'")
end end
end end
context 'when object is given' do context "when object is given" do
it "raises error when it doesn't respond to #call" do it "raises error when it doesn't respond to #call" do
callback = Object.new callback = Object.new
expect do expect do
Bar::CLI::Commands.after('alpha', callback) Bar::CLI::Commands.after("alpha", callback)
end.to raise_error( end.to raise_error(
Dry::CLI::InvalidCallbackError, Dry::CLI::InvalidCallbackError,
"expected `#{callback.inspect}' to respond to `#call'" "expected `#{callback.inspect}' to respond to `#call'"
@ -62,12 +62,12 @@ RSpec.describe Dry::CLI::Registry do
end end
end end
context 'when class is given' do context "when class is given" do
it 'raises error when #initialize arity is not equal to 0' do it "raises error when #initialize arity is not equal to 0" do
callback = Struct callback = Struct
expect do expect do
Bar::CLI::Commands.after('alpha', callback) Bar::CLI::Commands.after("alpha", callback)
end.to raise_error( end.to raise_error(
Dry::CLI::InvalidCallbackError, Dry::CLI::InvalidCallbackError,
"expected `#{callback.inspect}' to respond to `#initialize' with arity 0" "expected `#{callback.inspect}' to respond to `#initialize' with arity 0"

View File

@ -1,139 +1,139 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'dry/cli/utils/files' require "dry/cli/utils/files"
require 'securerandom' require "securerandom"
RSpec.describe Dry::CLI::Utils::Files do RSpec.describe Dry::CLI::Utils::Files do
let(:root) { Pathname.new(Dir.pwd).join('tmp', SecureRandom.uuid).tap(&:mkpath) } let(:root) { Pathname.new(Dir.pwd).join("tmp", SecureRandom.uuid).tap(&:mkpath) }
after do after do
FileUtils.remove_entry_secure(root) FileUtils.remove_entry_secure(root)
end end
describe '.touch' do describe ".touch" do
it 'creates an empty file' do it "creates an empty file" do
path = root.join('touch') path = root.join("touch")
described_class.touch(path) described_class.touch(path)
expect(path).to exist expect(path).to exist
expect(path).to have_content('') expect(path).to have_content("")
end end
it 'creates intermediate directories' do it "creates intermediate directories" do
path = root.join('path', 'to', 'file', 'touch') path = root.join("path", "to", "file", "touch")
described_class.touch(path) described_class.touch(path)
expect(path).to exist expect(path).to exist
expect(path).to have_content('') expect(path).to have_content("")
end end
it 'leaves untouched existing file' do it "leaves untouched existing file" do
path = root.join('touch') path = root.join("touch")
path.open('wb+') { |p| p.write('foo') } path.open("wb+") { |p| p.write("foo") }
described_class.touch(path) described_class.touch(path)
expect(path).to exist expect(path).to exist
expect(path).to have_content('foo') expect(path).to have_content("foo")
end end
end end
describe '.write' do describe ".write" do
it 'creates an file with given contents' do it "creates an file with given contents" do
path = root.join('write') path = root.join("write")
described_class.write(path, "Hello\nWorld") described_class.write(path, "Hello\nWorld")
expect(path).to exist expect(path).to exist
expect(path).to have_content("Hello\nWorld") expect(path).to have_content("Hello\nWorld")
end end
it 'creates intermediate directories' do it "creates intermediate directories" do
path = root.join('path', 'to', 'file', 'write') path = root.join("path", "to", "file", "write")
described_class.write(path, ':)') described_class.write(path, ":)")
expect(path).to exist expect(path).to exist
expect(path).to have_content(':)') expect(path).to have_content(":)")
end end
it 'overwrites file when it already exists' do it "overwrites file when it already exists" do
path = root.join('write') path = root.join("write")
described_class.write(path, 'many many many many words') described_class.write(path, "many many many many words")
described_class.write(path, 'new words') described_class.write(path, "new words")
expect(path).to exist expect(path).to exist
expect(path).to have_content('new words') expect(path).to have_content("new words")
end end
end end
describe '.cp' do describe ".cp" do
let(:source) { root.join('..', 'source') } let(:source) { root.join("..", "source") }
before do before do
source.delete if source.exist? source.delete if source.exist?
end end
it 'creates a file with given contents' do it "creates a file with given contents" do
described_class.write(source, 'the source') described_class.write(source, "the source")
destination = root.join('cp') destination = root.join("cp")
described_class.cp(source, destination) described_class.cp(source, destination)
expect(destination).to exist expect(destination).to exist
expect(destination).to have_content('the source') expect(destination).to have_content("the source")
end end
it 'creates intermediate directories' do it "creates intermediate directories" do
source = root.join('..', 'source') source = root.join("..", "source")
described_class.write(source, 'the source for intermediate directories') described_class.write(source, "the source for intermediate directories")
destination = root.join('cp', 'destination') destination = root.join("cp", "destination")
described_class.cp(source, destination) described_class.cp(source, destination)
expect(destination).to exist expect(destination).to exist
expect(destination).to have_content('the source for intermediate directories') expect(destination).to have_content("the source for intermediate directories")
end end
it 'overrides already existing file' do it "overrides already existing file" do
source = root.join('..', 'source') source = root.join("..", "source")
described_class.write(source, 'the source') described_class.write(source, "the source")
destination = root.join('cp') destination = root.join("cp")
described_class.write(destination, 'the destination') described_class.write(destination, "the destination")
described_class.cp(source, destination) described_class.cp(source, destination)
expect(destination).to exist expect(destination).to exist
expect(destination).to have_content('the source') expect(destination).to have_content("the source")
end end
end end
describe '.mkdir' do describe ".mkdir" do
it 'creates directory' do it "creates directory" do
path = root.join('mkdir') path = root.join("mkdir")
described_class.mkdir(path) described_class.mkdir(path)
expect(path).to be_directory expect(path).to be_directory
end end
it 'creates intermediate directories' do it "creates intermediate directories" do
path = root.join('path', 'to', 'mkdir') path = root.join("path", "to", "mkdir")
described_class.mkdir(path) described_class.mkdir(path)
expect(path).to be_directory expect(path).to be_directory
end end
end end
describe '.mkdir_p' do describe ".mkdir_p" do
it 'creates directory' do it "creates directory" do
directory = root.join('mkdir_p') directory = root.join("mkdir_p")
path = directory.join('file.rb') path = directory.join("file.rb")
described_class.mkdir_p(path) described_class.mkdir_p(path)
expect(directory).to be_directory expect(directory).to be_directory
expect(path).to_not exist expect(path).to_not exist
end end
it 'creates intermediate directories' do it "creates intermediate directories" do
directory = root.join('path', 'to', 'mkdir_p') directory = root.join("path", "to", "mkdir_p")
path = directory.join('file.rb') path = directory.join("file.rb")
described_class.mkdir_p(path) described_class.mkdir_p(path)
expect(directory).to be_directory expect(directory).to be_directory
@ -141,9 +141,9 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
end end
describe '.delete' do describe ".delete" do
it 'deletes path' do it "deletes path" do
path = root.join('delete', 'file') path = root.join("delete", "file")
described_class.touch(path) described_class.touch(path)
described_class.delete(path) described_class.delete(path)
@ -151,20 +151,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('delete', 'file') path = root.join("delete", "file")
expect { described_class.delete(path) }.to raise_error do |exception| expect { described_class.delete(path) }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.delete_directory' do describe ".delete_directory" do
it 'deletes directory' do it "deletes directory" do
path = root.join('delete', 'directory') path = root.join("delete", "directory")
described_class.mkdir(path) described_class.mkdir(path)
described_class.delete_directory(path) described_class.delete_directory(path)
@ -172,27 +172,27 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if directory doesn't exist" do it "raises error if directory doesn't exist" do
path = root.join('delete', 'directory') path = root.join("delete", "directory")
expect { described_class.delete_directory(path) }.to raise_error do |exception| expect { described_class.delete_directory(path) }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.unshift' do describe ".unshift" do
it 'adds a line at the top of the file' do it "adds a line at the top of the file" do
path = root.join('unshift.rb') path = root.join("unshift.rb")
content = <<~CONTENT content = <<~CONTENT
class Unshift class Unshift
end end
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.unshift(path, '# frozen_string_literal: true') described_class.unshift(path, "# frozen_string_literal: true")
expected = <<~CONTENT expected = <<~CONTENT
# frozen_string_literal: true # frozen_string_literal: true
@ -205,7 +205,7 @@ RSpec.describe Dry::CLI::Utils::Files do
# https://github.com/hanami/utils/issues/348 # https://github.com/hanami/utils/issues/348
it "adds a line at the top of a file that doesn't end with a newline" do it "adds a line at the top of a file that doesn't end with a newline" do
path = root.join('unshift_missing_newline.rb') path = root.join("unshift_missing_newline.rb")
content = "get '/tires', to: 'sunshine#index'" content = "get '/tires', to: 'sunshine#index'"
described_class.write(path, content) described_class.write(path, content)
@ -217,20 +217,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('unshift_no_exist.rb') path = root.join("unshift_no_exist.rb")
expect { described_class.unshift(path, '# frozen_string_literal: true') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.unshift(path, "# frozen_string_literal: true") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.append' do describe ".append" do
it 'adds a line at the bottom of the file' do it "adds a line at the bottom of the file" do
path = root.join('append.rb') path = root.join("append.rb")
content = <<~CONTENT content = <<~CONTENT
class Append class Append
end end
@ -251,7 +251,7 @@ RSpec.describe Dry::CLI::Utils::Files do
# https://github.com/hanami/utils/issues/348 # https://github.com/hanami/utils/issues/348
it "adds a line at the bottom of a file that doesn't end with a newline" do it "adds a line at the bottom of a file that doesn't end with a newline" do
path = root.join('append_missing_newline.rb') path = root.join("append_missing_newline.rb")
content = "root to: 'home#index'" content = "root to: 'home#index'"
described_class.write(path, content) described_class.write(path, content)
@ -266,20 +266,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('append_no_exist.rb') path = root.join("append_no_exist.rb")
expect { described_class.append(path, "\n Foo.register Append") }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.append(path, "\n Foo.register Append") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.replace_first_line' do describe ".replace_first_line" do
it 'replaces string target with replacement' do it "replaces string target with replacement" do
path = root.join('replace_string.rb') path = root.join("replace_string.rb")
content = <<~CONTENT content = <<~CONTENT
class Replace class Replace
def self.perform def self.perform
@ -288,7 +288,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.replace_first_line(path, 'perform', ' def self.call(input)') described_class.replace_first_line(path, "perform", " def self.call(input)")
expected = <<~CONTENT expected = <<~CONTENT
class Replace class Replace
@ -300,8 +300,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'replaces regexp target with replacement' do it "replaces regexp target with replacement" do
path = root.join('replace_regexp.rb') path = root.join("replace_regexp.rb")
content = <<~CONTENT content = <<~CONTENT
class Replace class Replace
def self.perform def self.perform
@ -310,7 +310,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.replace_first_line(path, /perform/, ' def self.call(input)') described_class.replace_first_line(path, /perform/, " def self.call(input)")
expected = <<~CONTENT expected = <<~CONTENT
class Replace class Replace
@ -322,8 +322,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'replaces only the first occurrence of target with replacement' do it "replaces only the first occurrence of target with replacement" do
path = root.join('replace_first.rb') path = root.join("replace_first.rb")
content = <<~CONTENT content = <<~CONTENT
class Replace class Replace
def self.perform def self.perform
@ -335,7 +335,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.replace_first_line(path, 'perform', ' def self.call(input)') described_class.replace_first_line(path, "perform", " def self.call(input)")
expected = <<~CONTENT expected = <<~CONTENT
class Replace class Replace
@ -350,8 +350,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if target cannot be found in path' do it "raises error if target cannot be found in path" do
path = root.join('replace_not_found.rb') path = root.join("replace_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
class Replace class Replace
def self.perform def self.perform
@ -361,7 +361,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.replace_first_line(path, 'not existing target', ' def self.call(input)') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.replace_first_line(path, "not existing target", " def self.call(input)") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -370,20 +370,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('replace_no_exist.rb') path = root.join("replace_no_exist.rb")
expect { described_class.replace_first_line(path, 'perform', ' def self.call(input)') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.replace_first_line(path, "perform", " def self.call(input)") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.replace_last_line' do describe ".replace_last_line" do
it 'replaces string target with replacement' do it "replaces string target with replacement" do
path = root.join('replace_last_string.rb') path = root.join("replace_last_string.rb")
content = <<~CONTENT content = <<~CONTENT
class ReplaceLast class ReplaceLast
def self.perform def self.perform
@ -392,7 +392,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.replace_last_line(path, 'perform', ' def self.call(input)') described_class.replace_last_line(path, "perform", " def self.call(input)")
expected = <<~CONTENT expected = <<~CONTENT
class ReplaceLast class ReplaceLast
@ -404,8 +404,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'replaces regexp target with replacement' do it "replaces regexp target with replacement" do
path = root.join('replace_last_regexp.rb') path = root.join("replace_last_regexp.rb")
content = <<~CONTENT content = <<~CONTENT
class ReplaceLast class ReplaceLast
def self.perform def self.perform
@ -414,7 +414,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.replace_last_line(path, /perform/, ' def self.call(input)') described_class.replace_last_line(path, /perform/, " def self.call(input)")
expected = <<~CONTENT expected = <<~CONTENT
class ReplaceLast class ReplaceLast
@ -426,8 +426,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'replaces only the last occurrence of target with replacement' do it "replaces only the last occurrence of target with replacement" do
path = root.join('replace_last.rb') path = root.join("replace_last.rb")
content = <<~CONTENT content = <<~CONTENT
class ReplaceLast class ReplaceLast
def self.perform def self.perform
@ -439,7 +439,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.replace_last_line(path, 'perform', ' def self.call(input)') described_class.replace_last_line(path, "perform", " def self.call(input)")
expected = <<~CONTENT expected = <<~CONTENT
class ReplaceLast class ReplaceLast
@ -454,8 +454,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if target cannot be found in path' do it "raises error if target cannot be found in path" do
path = root.join('replace_last_not_found.rb') path = root.join("replace_last_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
class ReplaceLast class ReplaceLast
def self.perform def self.perform
@ -465,7 +465,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.replace_last_line(path, 'not existing target', ' def self.call(input)') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.replace_last_line(path, "not existing target", " def self.call(input)") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -474,20 +474,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('replace_last_no_exist.rb') path = root.join("replace_last_no_exist.rb")
expect { described_class.replace_last_line(path, 'perform', ' def self.call(input)') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.replace_last_line(path, "perform", " def self.call(input)") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.inject_line_before' do describe ".inject_line_before" do
it 'injects line before target (string)' do it "injects line before target (string)" do
path = root.join('inject_before_string.rb') path = root.join("inject_before_string.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectBefore class InjectBefore
def self.call def self.call
@ -496,7 +496,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_before(path, 'call', ' # It performs the operation') described_class.inject_line_before(path, "call", " # It performs the operation")
expected = <<~CONTENT expected = <<~CONTENT
class InjectBefore class InjectBefore
@ -509,8 +509,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'injects line before target (regexp)' do it "injects line before target (regexp)" do
path = root.join('inject_before_regexp.rb') path = root.join("inject_before_regexp.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectBefore class InjectBefore
def self.call def self.call
@ -519,7 +519,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_before(path, /call/, ' # It performs the operation') described_class.inject_line_before(path, /call/, " # It performs the operation")
expected = <<~CONTENT expected = <<~CONTENT
class InjectBefore class InjectBefore
@ -532,8 +532,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if target cannot be found in path' do it "raises error if target cannot be found in path" do
path = root.join('inject_before_not_found.rb') path = root.join("inject_before_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectBefore class InjectBefore
def self.call def self.call
@ -543,7 +543,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.inject_line_before(path, 'not existing target', ' # It performs the operation') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_before(path, "not existing target", " # It performs the operation") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -552,20 +552,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('inject_before_no_exist.rb') path = root.join("inject_before_no_exist.rb")
expect { described_class.inject_line_before(path, 'call', ' # It performs the operation') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_before(path, "call", " # It performs the operation") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.inject_line_before_last' do describe ".inject_line_before_last" do
it 'injects line before last target (string)' do it "injects line before last target (string)" do
path = root.join('inject_before_last_string.rb') path = root.join("inject_before_last_string.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectBefore class InjectBefore
def self.call def self.call
@ -576,7 +576,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_before_last(path, 'call', ' # It performs the operation') described_class.inject_line_before_last(path, "call", " # It performs the operation")
expected = <<~CONTENT expected = <<~CONTENT
class InjectBefore class InjectBefore
@ -591,8 +591,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'injects line before last target (regexp)' do it "injects line before last target (regexp)" do
path = root.join('inject_before_last_regexp.rb') path = root.join("inject_before_last_regexp.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectBefore class InjectBefore
def self.call def self.call
@ -603,7 +603,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_before_last(path, /call/, ' # It performs the operation') described_class.inject_line_before_last(path, /call/, " # It performs the operation")
expected = <<~CONTENT expected = <<~CONTENT
class InjectBefore class InjectBefore
@ -618,8 +618,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if target cannot be found in path' do it "raises error if target cannot be found in path" do
path = root.join('inject_before_last_not_found.rb') path = root.join("inject_before_last_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectBefore class InjectBefore
def self.call def self.call
@ -631,7 +631,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.inject_line_before_last(path, 'not existing target', ' # It performs the operation') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_before_last(path, "not existing target", " # It performs the operation") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -640,20 +640,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('inject_before_last_no_exist.rb') path = root.join("inject_before_last_no_exist.rb")
expect { described_class.inject_line_before_last(path, 'call', ' # It performs the operation') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_before_last(path, "call", " # It performs the operation") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.inject_line_after' do describe ".inject_line_after" do
it 'injects line after target (string)' do it "injects line after target (string)" do
path = root.join('inject_after.rb') path = root.join("inject_after.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectAfter class InjectAfter
def self.call def self.call
@ -662,7 +662,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_after(path, 'call', ' :result') described_class.inject_line_after(path, "call", " :result")
expected = <<~CONTENT expected = <<~CONTENT
class InjectAfter class InjectAfter
@ -675,8 +675,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'injects line after target (regexp)' do it "injects line after target (regexp)" do
path = root.join('inject_after.rb') path = root.join("inject_after.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectAfter class InjectAfter
def self.call def self.call
@ -685,7 +685,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_after(path, /call/, ' :result') described_class.inject_line_after(path, /call/, " :result")
expected = <<~CONTENT expected = <<~CONTENT
class InjectAfter class InjectAfter
@ -698,8 +698,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if target cannot be found in path' do it "raises error if target cannot be found in path" do
path = root.join('inject_after_not_found.rb') path = root.join("inject_after_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectAfter class InjectAfter
def self.call def self.call
@ -709,7 +709,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.inject_line_after(path, 'not existing target', ' :result') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_after(path, "not existing target", " :result") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -718,20 +718,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('inject_after_no_exist.rb') path = root.join("inject_after_no_exist.rb")
expect { described_class.inject_line_after(path, 'call', ' :result') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_after(path, "call", " :result") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.inject_line_after_last' do describe ".inject_line_after_last" do
it 'injects line after last target (string)' do it "injects line after last target (string)" do
path = root.join('inject_after_last.rb') path = root.join("inject_after_last.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectAfter class InjectAfter
def self.call def self.call
@ -742,7 +742,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_after_last(path, 'call', ' :result') described_class.inject_line_after_last(path, "call", " :result")
expected = <<~CONTENT expected = <<~CONTENT
class InjectAfter class InjectAfter
@ -757,8 +757,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'injects line after last target (regexp)' do it "injects line after last target (regexp)" do
path = root.join('inject_after_last.rb') path = root.join("inject_after_last.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectAfter class InjectAfter
def self.call def self.call
@ -769,7 +769,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.inject_line_after_last(path, /call/, ' :result') described_class.inject_line_after_last(path, /call/, " :result")
expected = <<~CONTENT expected = <<~CONTENT
class InjectAfter class InjectAfter
@ -784,8 +784,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if target cannot be found in path' do it "raises error if target cannot be found in path" do
path = root.join('inject_after_last_not_found.rb') path = root.join("inject_after_last_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
class InjectAfter class InjectAfter
def self.call def self.call
@ -797,7 +797,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.inject_line_after_last(path, 'not existing target', ' :result') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_after_last(path, "not existing target", " :result") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -806,20 +806,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('inject_after_last_no_exist.rb') path = root.join("inject_after_last_no_exist.rb")
expect { described_class.inject_line_after_last(path, 'call', ' :result') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.inject_line_after_last(path, "call", " :result") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.remove_line' do describe ".remove_line" do
it 'removes line (string)' do it "removes line (string)" do
path = root.join('remove_line_string.rb') path = root.join("remove_line_string.rb")
content = <<~CONTENT content = <<~CONTENT
# frozen_string_literal: true # frozen_string_literal: true
class RemoveLine class RemoveLine
@ -829,7 +829,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.remove_line(path, 'frozen') described_class.remove_line(path, "frozen")
expected = <<~CONTENT expected = <<~CONTENT
class RemoveLine class RemoveLine
@ -841,8 +841,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'removes line (regexp)' do it "removes line (regexp)" do
path = root.join('remove_line_regexp.rb') path = root.join("remove_line_regexp.rb")
content = <<~CONTENT content = <<~CONTENT
# frozen_string_literal: true # frozen_string_literal: true
class RemoveLine class RemoveLine
@ -864,8 +864,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if target cannot be found in path' do it "raises error if target cannot be found in path" do
path = root.join('remove_line_not_found.rb') path = root.join("remove_line_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
# frozen_string_literal: true # frozen_string_literal: true
class RemoveLine class RemoveLine
@ -876,7 +876,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.remove_line(path, 'not existing target') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.remove_line(path, "not existing target") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -885,20 +885,20 @@ RSpec.describe Dry::CLI::Utils::Files do
end end
it "raises error if path doesn't exist" do it "raises error if path doesn't exist" do
path = root.join('remove_line_no_exist.rb') path = root.join("remove_line_no_exist.rb")
expect { described_class.remove_line(path, 'frozen') }.to raise_error do |exception| expect { described_class.remove_line(path, "frozen") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
expect(path).to_not exist expect(path).to_not exist
end end
end end
describe '.remove_block' do describe ".remove_block" do
it 'removes block from Ruby file' do it "removes block from Ruby file" do
path = root.join('remove_block_simple.rb') path = root.join("remove_block_simple.rb")
content = <<~CONTENT content = <<~CONTENT
class RemoveBlock class RemoveBlock
configure do configure do
@ -908,7 +908,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.remove_block(path, 'configure') described_class.remove_block(path, "configure")
expected = <<~CONTENT expected = <<~CONTENT
class RemoveBlock class RemoveBlock
@ -918,8 +918,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'removes nested block from Ruby file' do it "removes nested block from Ruby file" do
path = root.join('remove_block_simple.rb') path = root.join("remove_block_simple.rb")
content = <<~CONTENT content = <<~CONTENT
class RemoveBlock class RemoveBlock
configure do configure do
@ -935,7 +935,7 @@ RSpec.describe Dry::CLI::Utils::Files do
CONTENT CONTENT
described_class.write(path, content) described_class.write(path, content)
described_class.remove_block(path, 'assets') described_class.remove_block(path, "assets")
expected = <<~CONTENT expected = <<~CONTENT
class RemoveBlock class RemoveBlock
@ -949,8 +949,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(expected) expect(path).to have_content(expected)
end end
it 'raises error if block cannot be found in path' do it "raises error if block cannot be found in path" do
path = root.join('remove_block_not_found.rb') path = root.join("remove_block_not_found.rb")
content = <<~CONTENT content = <<~CONTENT
class RemoveBlock class RemoveBlock
configure do configure do
@ -961,7 +961,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.remove_block(path, 'not existing target') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.remove_block(path, "not existing target") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -969,8 +969,8 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(content) expect(path).to have_content(content)
end end
it 'raises error if block cannot be found' do it "raises error if block cannot be found" do
path = root.join('remove_block_string_simple.rb') path = root.join("remove_block_string_simple.rb")
content = <<~CONTENT content = <<~CONTENT
class RemoveBlock class RemoveBlock
configure do configure do
@ -981,7 +981,7 @@ RSpec.describe Dry::CLI::Utils::Files do
described_class.write(path, content) described_class.write(path, content)
expect { described_class.remove_block(path, 'not existing target') }.to raise_error do |exception| # rubocop:disable Metrics/LineLength expect { described_class.remove_block(path, "not existing target") }.to raise_error do |exception|
expect(exception).to be_kind_of(ArgumentError) expect(exception).to be_kind_of(ArgumentError)
expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.") expect(exception.message).to eq("Cannot find `not existing target' inside `#{path}'.")
end end
@ -989,55 +989,55 @@ RSpec.describe Dry::CLI::Utils::Files do
expect(path).to have_content(content) expect(path).to have_content(content)
end end
it 'raises an error when the file was not found' do it "raises an error when the file was not found" do
path = root.join('remove_block_not_found.rb') path = root.join("remove_block_not_found.rb")
expect { described_class.remove_block(path, 'configure') }.to raise_error do |exception| expect { described_class.remove_block(path, "configure") }.to raise_error do |exception|
expect(exception).to be_kind_of(Errno::ENOENT) expect(exception).to be_kind_of(Errno::ENOENT)
expect(exception.message).to match('No such file or directory') expect(exception.message).to match("No such file or directory")
end end
end end
end end
describe '.exist?' do describe ".exist?" do
it 'returns true for file' do it "returns true for file" do
path = root.join('exist_file') path = root.join("exist_file")
described_class.touch(path) described_class.touch(path)
expect(described_class.exist?(path)).to be(true) expect(described_class.exist?(path)).to be(true)
end end
it 'returns true for directory' do it "returns true for directory" do
path = root.join('exist_directory') path = root.join("exist_directory")
described_class.mkdir(path) described_class.mkdir(path)
expect(described_class.exist?(path)).to be(true) expect(described_class.exist?(path)).to be(true)
end end
it 'returns false for non-existing file' do it "returns false for non-existing file" do
path = root.join('exist_not_found') path = root.join("exist_not_found")
expect(described_class.exist?(path)).to be(false) expect(described_class.exist?(path)).to be(false)
end end
end end
describe '.directory?' do describe ".directory?" do
it 'returns true for directory' do it "returns true for directory" do
path = root.join('directory_directory') path = root.join("directory_directory")
described_class.mkdir(path) described_class.mkdir(path)
expect(described_class.exist?(path)).to be(true) expect(described_class.exist?(path)).to be(true)
end end
it 'returns false for file' do it "returns false for file" do
path = root.join('directory_file') path = root.join("directory_file")
described_class.touch(path) described_class.touch(path)
expect(described_class.directory?(path)).to be(false) expect(described_class.directory?(path)).to be(false)
end end
it 'returns false for non-existing path' do it "returns false for non-existing path" do
path = root.join('directory_not_found') path = root.join("directory_not_found")
expect(described_class.exist?(path)).to be(false) expect(described_class.exist?(path)).to be(false)
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe 'Dry::CLI::VERSION' do RSpec.describe "Dry::CLI::VERSION" do
it 'exposes version' do it "exposes version" do
expect(Dry::CLI::VERSION).to eq('0.6.0') expect(Dry::CLI::VERSION).to eq("0.6.0")
end end
end end