lib/minitest_to_rspec/cli.rb
# frozen_string_literal: true
require 'fileutils'
require 'minitest_to_rspec'
require 'optimist'
module MinitestToRspec
# Command-Line Interface (CLI) instantiated by `bin/mt2rspec`
class CLI
E_USAGE = 1
E_FILE_NOT_FOUND = 2
E_FILE_ALREADY_EXISTS = 3
E_CONVERT_FAIL = 4
E_CANNOT_CREATE_TARGET_DIR = 5
BANNER = <<~EOS
Usage: mt2rspec [--rails] [--mocha] source_file [target_file]
Reads source_file, writes target_file. If target_file is omitted,
its location will be inferred. For example, test/fruit/banana_test.rb
implies spec/fruit/banana_spec.rb. If the target directory doesn't
exist, it will be created.
Options:
EOS
OPT_MOCHA = 'Convert mocha to rspec-mocks. (Experimental)'
OPT_RAILS = <<~EOS.tr("\n", ' ').freeze
Requires rails_helper instead of spec_helper.
Passes :type metadatum to RSpec.describe.
EOS
attr_reader :source, :target
def initialize(args)
opts = parse_args(args)
@rails = opts[:rails]
@mocha = opts[:mocha]
case args.length
when 2
@source, @target = args
when 1
@source = args[0]
@target = infer_target_from @source
else
warn 'Please specify source file'
exit E_USAGE
end
end
def run
assert_file_exists(source)
assert_file_does_not_exist(target)
ensure_target_directory(target)
write_target(converter.convert(read_source, source))
rescue Error => e
warn "Failed to convert: #{e}"
exit E_CONVERT_FAIL
end
private
def assert_file_exists(file)
unless File.exist?(file)
warn "File not found: #{file}"
exit(E_FILE_NOT_FOUND)
end
end
def assert_file_does_not_exist(file)
if File.exist?(file)
warn "File already exists: #{file}"
exit(E_FILE_ALREADY_EXISTS)
end
end
def converter
Converter.new(mocha: @mocha, rails: @rails)
end
def ensure_target_directory(target)
dir = File.dirname(target)
return if Dir.exist?(dir)
begin
FileUtils.mkdir_p(dir)
rescue SystemCallError => e
warn "Cannot create target dir: #{dir}"
warn e.message
exit E_CANNOT_CREATE_TARGET_DIR
end
end
def infer_target_from(source)
source
.gsub(/\Atest/, 'spec')
.gsub(/_test.rb\Z/, '_spec.rb')
end
def parse_args(args)
Optimist.options(args) do
version MinitestToRspec.gem_version.to_s
banner BANNER
opt :rails, OPT_RAILS, short: :none
opt :mocha, OPT_MOCHA, short: :none
end
end
def read_source
File.read(source)
end
def write_target(str)
File.write(target, str)
end
end
end