Skip to content

Commit 15dad90

Browse files
committed
edge cases
1 parent a560c99 commit 15dad90

File tree

8 files changed

+212
-1
lines changed

8 files changed

+212
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
/spec/reports/
88
/tmp/
99
/target/
10+
/vendor
1011

1112
Gemfile.lock
1213

Rakefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ GEMSPEC = Gem::Specification.load('code_ownership.gemspec')
55
task build: 'pkg:ruby'
66

77
# task default: %w[env:dev compile spec]
8-
task default: %w[env:dev compile]
8+
task default: %w[env:dev compile spec]
6.73 MB
Binary file not shown.

spec/lib/code_ownership/cli_spec.rb

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,40 @@
6161
end
6262
end
6363
end
64+
65+
context 'with --skip-autocorrect' do
66+
let(:argv) { ['validate', '--skip-autocorrect'] }
67+
68+
it 'passes autocorrect: false' do
69+
expect(CodeOwnership).to receive(:validate!) do |args|
70+
expect(args[:autocorrect]).to eq false
71+
expect(args[:stage_changes]).to eq true
72+
end
73+
subject
74+
end
75+
end
76+
77+
context 'with --skip-stage' do
78+
let(:argv) { ['validate', '--skip-stage'] }
79+
80+
it 'passes stage_changes: false' do
81+
expect(CodeOwnership).to receive(:validate!) do |args|
82+
expect(args[:autocorrect]).to eq true
83+
expect(args[:stage_changes]).to eq false
84+
end
85+
subject
86+
end
87+
end
88+
89+
context 'with --help' do
90+
let(:argv) { ['validate', '--help'] }
91+
92+
it 'shows help and exits' do
93+
expect(CodeOwnership).not_to receive(:validate!)
94+
expect(CodeOwnership::Cli).to receive(:puts).at_least(:once)
95+
expect { subject }.to raise_error(SystemExit)
96+
end
97+
end
6498
end
6599

66100
context 'for_team' do
@@ -82,6 +116,31 @@
82116
expect(CodeOwnership::Cli).to receive(:puts).with('# Code Ownership Report for `My Team` Team')
83117
subject
84118
end
119+
120+
context 'with no team provided' do
121+
let(:argv) { ['for_team'] }
122+
123+
it 'raises argument error' do
124+
expect { subject }.to raise_error("Please pass in one team. Use `#{described_class::EXECUTABLE} for_team --help` for more info")
125+
end
126+
end
127+
128+
context 'with multiple teams provided' do
129+
let(:argv) { %w[for_team A B] }
130+
131+
it 'raises argument error' do
132+
expect { subject }.to raise_error("Please pass in one team. Use `#{described_class::EXECUTABLE} for_team --help` for more info")
133+
end
134+
end
135+
136+
context 'with --help' do
137+
let(:argv) { ['for_team', '--help'] }
138+
139+
it 'shows help and exits' do
140+
expect(CodeOwnership::Cli).to receive(:puts).at_least(:once)
141+
expect { subject }.to raise_error(SystemExit)
142+
end
143+
end
85144
end
86145

87146
describe 'for_file' do
@@ -164,6 +223,28 @@ def initialize
164223
end
165224
end
166225
end
226+
227+
context 'when file is unowned' do
228+
let(:argv) { ['for_file', 'app/services/unowned.rb'] }
229+
230+
it 'prints Unowned' do
231+
allow(CodeOwnership).to receive(:for_file).and_return(nil)
232+
expect(CodeOwnership::Cli).to receive(:puts).with(<<~MSG)
233+
Team: Unowned
234+
Team YML: Unowned
235+
MSG
236+
subject
237+
end
238+
end
239+
240+
context 'with --help' do
241+
let(:argv) { ['for_file', '--help'] }
242+
243+
it 'shows help and exits' do
244+
expect(CodeOwnership::Cli).to receive(:puts).at_least(:once)
245+
expect { subject }.to raise_error(SystemExit)
246+
end
247+
end
167248
end
168249

169250
describe 'using unknown command' do

spec/lib/code_ownership/private/file_path_finder_spec.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,48 @@ class TestClass; end # rubocop:disable Lint/ConstantDefinitionInBlock, Lint/Empt
3636
end
3737
end
3838
end
39+
40+
describe '.from_backtrace' do
41+
subject(:files) { described_class.from_backtrace(backtrace).to_a }
42+
43+
context 'when backtrace is nil' do
44+
let(:backtrace) { nil }
45+
46+
it 'returns an empty array' do
47+
expect(files).to eq([])
48+
end
49+
end
50+
51+
context 'when backtrace is empty' do
52+
let(:backtrace) { [] }
53+
54+
it 'returns an empty array' do
55+
expect(files).to eq([])
56+
end
57+
end
58+
59+
context 'on Ruby < 3.4 backtrace format (backticks)' do
60+
let(:backtrace) do
61+
["./app/models/user.rb:12:in `save'", "app/controllers/some_controller.rb:43:in `block (2 levels) in create'"]
62+
end
63+
64+
it 'extracts file paths' do
65+
expect(files).to include('app/models/user.rb', 'app/controllers/some_controller.rb')
66+
end
67+
end
68+
69+
context 'on Ruby >= 3.4 backtrace format (single quotes)' do
70+
let(:backtrace) do
71+
["./app/models/user.rb:12:in 'save'", "app/controllers/some_controller.rb:43:in 'block (2 levels) in create'"]
72+
end
73+
74+
it 'extracts file paths' do
75+
if RUBY_VERSION >= '3.4.0'
76+
expect(files).to include('app/models/user.rb', 'app/controllers/some_controller.rb')
77+
else
78+
skip 'Ruby version < 3.4 does not use single quote backtrace format'
79+
end
80+
end
81+
end
82+
end
3983
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe CodeOwnership::Private::PackOwnershipValidator do
4+
it 'permits the owner top-level key' do
5+
expect(described_class.new.permitted_keys).to include('owner')
6+
end
7+
end
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe CodeOwnership::Private::TeamFinder do
4+
describe '.for_file' do
5+
let(:file_path) { 'packs/my_pack/owned_file.rb' }
6+
7+
before do
8+
create_non_empty_application
9+
end
10+
11+
it 'caches positive results' do
12+
allow(RustCodeOwners).to receive(:for_file).with(file_path)
13+
.and_return({ team_name: 'Bar' }, nil)
14+
15+
first = described_class.for_file(file_path)
16+
second = described_class.for_file(file_path)
17+
18+
expect(first).to eq(CodeTeams.find('Bar'))
19+
expect(second).to eq(CodeTeams.find('Bar'))
20+
expect(CodeOwnership::Private::FilePathTeamCache.cached?(file_path)).to be true
21+
end
22+
23+
it 'does not cache when rust returns nil' do
24+
allow(RustCodeOwners).to receive(:for_file).with(file_path).and_return(nil)
25+
26+
expect(described_class.for_file(file_path)).to be_nil
27+
expect(CodeOwnership::Private::FilePathTeamCache.cached?(file_path)).to be false
28+
end
29+
30+
it 'caches nil when team_name is nil' do
31+
allow(RustCodeOwners).to receive(:for_file).with(file_path).and_return({ team_name: nil })
32+
33+
expect(described_class.for_file(file_path)).to be_nil
34+
expect(CodeOwnership::Private::FilePathTeamCache.cached?(file_path)).to be true
35+
expect(CodeOwnership::Private::FilePathTeamCache.get(file_path)).to be_nil
36+
end
37+
end
38+
39+
describe '.for_backtrace' do
40+
it 'returns nil for nil backtrace' do
41+
expect(described_class.for_backtrace(nil)).to be_nil
42+
end
43+
end
44+
45+
describe '.first_owned_file_for_backtrace' do
46+
it 'returns nil for nil backtrace' do
47+
expect(described_class.first_owned_file_for_backtrace(nil)).to be_nil
48+
end
49+
end
50+
end

spec/lib/code_ownership_spec.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,22 @@
127127
expect(subject).to be_nil
128128
end
129129
end
130+
131+
context 'with unknown owner' do
132+
let(:raw_hash) { { 'owner' => 'Does Not Exist' } }
133+
134+
it 'raises helpful error' do
135+
expect { subject }.to raise_error(StandardError, /Could not find team with name:/)
136+
end
137+
end
138+
139+
context 'with empty owner string' do
140+
let(:raw_hash) { { 'owner' => '' } }
141+
142+
it 'raises helpful error' do
143+
expect { subject }.to raise_error(StandardError, /Could not find team with name:/)
144+
end
145+
end
130146
end
131147

132148
describe '.for_backtrace' do
@@ -151,6 +167,12 @@
151167
end
152168
end
153169
end
170+
171+
context 'with nil backtrace' do
172+
it 'returns nil' do
173+
expect(described_class.for_backtrace(nil)).to be_nil
174+
end
175+
end
154176
end
155177

156178
describe '.first_owned_file_for_backtrace' do
@@ -183,5 +205,11 @@
183205
end
184206
end
185207
end
208+
209+
context 'with nil backtrace' do
210+
it 'returns nil' do
211+
expect(described_class.first_owned_file_for_backtrace(nil)).to be_nil
212+
end
213+
end
186214
end
187215
end

0 commit comments

Comments
 (0)