Skip to content

Commit

Permalink
(maint) Add unit tests for PDK::Validate::RubocopValidator
Browse files Browse the repository at this point in the history
  • Loading branch information
rodjek committed Jul 11, 2017
1 parent 63843a8 commit 799f753
Show file tree
Hide file tree
Showing 2 changed files with 301 additions and 1 deletion.
6 changes: 5 additions & 1 deletion lib/pdk/validators/ruby/rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def self.cmd
'rubocop'
end

def self.pattern
['**/*.rb']
end

def self.spinner_text(_targets = nil)
_('Checking Ruby code style')
end
Expand All @@ -34,7 +38,7 @@ def self.parse_output(report, result, _targets)
begin
json_data = JSON.parse(result[:stdout])
rescue JSON::ParserError
json_data = []
json_data = {}
end

return unless json_data.key?('files')
Expand Down
296 changes: 296 additions & 0 deletions spec/pdk/validate/rubocop_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
require 'spec_helper'
require 'rubocop'
require 'ostruct'

shared_examples_for 'it sets the common options' do
it 'sets the output format as JSON' do
expect(command_args.first(2)).to eq(['--format', 'json'])
end

it 'only sets 1 output format' do
expect(command_args.count('--format')).to eq(1)
end

it 'appends the targets to the command arguments' do
expect(command_args.last(targets.count)).to eq(targets)
end
end

describe PDK::Validate::Rubocop do
let(:module_root) { File.join('path', 'to', 'test', 'module') }

before(:each) do
allow(PDK::Util).to receive(:module_root).and_return(module_root)
allow(File).to receive(:directory?).with(module_root).and_return(true)
end

it 'defines the base validator attributes' do
expect(described_class).to have_attributes(
name: 'rubocop',
cmd: 'rubocop',
spinner_text: a_string_matching(%r{ruby code style}i),
)
end

describe '.parse_targets' do
subject(:target_files) { described_class.parse_targets(targets: targets) }

let(:globbed_files) { [] }
let(:glob_pattern) { File.join(module_root, described_class.pattern) }

before(:each) do
allow(Dir).to receive(:glob).with(glob_pattern).and_return(globbed_files)
end

context 'when given no targets' do
let(:targets) { [] }

context 'and the module contains .rb files' do
let(:globbed_files) do
[
File.join(module_root, 'lib', 'test.rb'),
File.join(module_root, 'spec', 'spec_helper.rb'),
]
end

it 'returns the paths to all the .rb files in the module' do
expect(target_files).to eq(globbed_files)
end
end

context 'and the module contains no .rb files' do
it 'returns no targets' do
expect(target_files).to eq([])
end
end
end

context 'when given specific target files' do
let(:targets) { ['target1.rb', 'target2'] }

before(:each) do
targets.each do |target|
allow(File).to receive(:directory?).with(target).and_return(false)
end
end

it 'returns the targets' do
expect(target_files).to eq(targets)
end
end

context 'when given a specific target directory' do
let(:targets) { [File.join('path', 'to', 'target', 'directory')] }
let(:glob_pattern) { File.join(targets.first, described_class.pattern) }

before(:each) do
allow(File).to receive(:directory?).with(targets.first).and_return(true)
end

context 'and the directory contains .rb files' do
let(:globbed_files) { [File.join(targets.first, 'test.rb')] }

it 'returns the paths to the .rb files in the directory' do
expect(target_files).to eq(globbed_files)
end
end

context 'and the directory contains no .rb files' do
it 'returns no targets' do
expect(target_files).to eq([])
end
end
end
end

describe '.parse_options' do
subject(:command_args) { described_class.parse_options(options, targets) }

let(:options) { {} }
let(:targets) { %w[target1 target2] }

context 'when auto-correct is enabled' do
let(:options) { { auto_correct: true } }

it_behaves_like 'it sets the common options'

it 'includes the --auto-correct flag' do
expect(command_args).to include('--auto-correct')
end
end

context 'when auto-correct is disabled' do
it_behaves_like 'it sets the common options'

it 'does not include the --auto-correct flag' do
expect(command_args).not_to include('--auto-correct')
end
end
end

describe '.parse_output' do
subject(:parse_output) { described_class.parse_output(report, { stdout: rubocop_json }, []) }

let(:rubocop_report) { RuboCop::Formatter::JSONFormatter.new(nil) }
let(:rubocop_json) { rubocop_report.output_hash.to_json }
let(:report) { PDK::Report.new }
let(:test_file) { File.join(module_root, 'lib', 'test.rb') }

def mock_offense(severity, message, cop_name, corrected, line, column)
OpenStruct.new(
severity: OpenStruct.new(name: severity),
message: message,
cop_name: cop_name,
corrected?: corrected,
line: line,
real_column: column,
location: OpenStruct.new(length: 0),
)
end

context 'when rubocop generates bad JSON' do
let(:rubocop_json) { '' }

it 'does not add any events to the report' do
expect(report).not_to receive(:add_event)

parse_output
end
end

context 'when rubocop has not tested any files' do
it 'does not add any events to the report' do
expect(report).not_to receive(:add_event)

parse_output
end
end

context 'when the rubocop output has no offenses for a file' do
before(:each) do
rubocop_report.file_finished(test_file, [])
end

it 'adds a passing event to the report' do
expect(report).to receive(:add_event).with(
file: test_file,
source: described_class.name,
state: :passed,
severity: :ok,
)

parse_output
end
end

context 'when the rubocop output has an offense for a file' do
let(:offenses) do
[
mock_offense('error', 'test message', 'Test/Cop', false, 1, 2),
]
end

before(:each) do
rubocop_report.file_finished(test_file, offenses)
end

it 'adds a failure event to the report' do
expect(report).to receive(:add_event).with(
file: test_file,
source: described_class.name,
state: :failure,
severity: 'error',
message: 'test message',
line: 1,
column: 2,
test: 'Test/Cop',
)

parse_output
end

context 'when rubocop has corrected the offense' do
let(:offenses) do
[
mock_offense('error', 'test message', 'Test/Cop', true, 1, 2),
]
end

it 'changes the severity of the event to "corrected"' do
expect(report).to receive(:add_event).with(
file: test_file,
source: described_class.name,
state: :failure,
severity: 'corrected',
message: 'test message',
line: 1,
column: 2,
test: 'Test/Cop',
)

parse_output
end
end
end

context 'when the rubocop output has information for multiple files' do
let(:test_files) do
{
File.join(module_root, 'spec', 'spec_helper.rb') => [],
File.join(module_root, 'lib', 'fail.rb') => [
mock_offense('error', 'correctable error', 'Test/Cop', true, 1, 2),
mock_offense('warning', 'uncorrectable thing', 'Test/Cop2', false, 3, 4),
],
}
end

before(:each) do
test_files.each do |file, offenses|
rubocop_report.file_finished(file, offenses)
end
allow(report).to receive(:add_event).with(anything)
end

it 'adds a passing event to the report for the file with no offenses' do
expect(report).to receive(:add_event).with(
file: File.join(module_root, 'spec', 'spec_helper.rb'),
source: described_class.name,
state: :passed,
severity: :ok,
)

parse_output
end

it 'adds a corrected failure event to the report for the file with offenses' do
expect(report).to receive(:add_event).with(
file: File.join(module_root, 'lib', 'fail.rb'),
source: described_class.name,
state: :failure,
severity: 'corrected',
message: 'correctable error',
line: 1,
column: 2,
test: 'Test/Cop',
)

parse_output
end

it 'adds a failure event to the report for the file with offenses' do
expect(report).to receive(:add_event).with(
file: File.join(module_root, 'lib', 'fail.rb'),
source: described_class.name,
state: :failure,
severity: 'warning',
message: 'uncorrectable thing',
line: 3,
column: 4,
test: 'Test/Cop2',
)

parse_output
end
end
end
end

0 comments on commit 799f753

Please sign in to comment.