Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(deps-dev): bump rubocop-rspec from 2.26.1 to 2.28.0 #13

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,22 @@ GEM
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-ast (1.31.2)
parser (>= 3.3.0.4)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-performance (1.20.2)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.26.1)
rubocop-rspec (2.28.0)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
rubocop-rspec_rails (~> 2.28)
rubocop-rspec_rails (2.28.2)
rubocop (~> 1.40)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
sawyer (0.9.2)
Expand Down
55 changes: 3 additions & 52 deletions lib/code_review_leaderboard.rb
Original file line number Diff line number Diff line change
@@ -1,65 +1,16 @@
require_relative "code_review_leaderboard/version"

require_relative "async/wait_all_throttled"

require "code_review_leaderboard/config"
require "code_review_leaderboard/formatter"
require "code_review_leaderboard/organization"
require "code_review_leaderboard/pulls"
require "code_review_leaderboard/repository"
require "code_review_leaderboard/reviews"
require "code_review_leaderboard/spinner"
require_relative "code_review_leaderboard/runner"

module CodeReviewLeaderboard
extend self

def initialize!
Config.initialize!

raise ConfigurationError, "Access token is required" if Config.access_token.nil?
raise ConfigurationError, "Access token is required" if Config.access_token.blank?
raise ConfigurationError, "Repository or owner is required" if Config.repositories.empty? && Config.organization.blank?
end

def start
puts Formatter.new(reviews).to_table
end

private

def repositories
@@repositories ||= if Config.repositories.present?
Config.repositories.map { Repository.new(name: _1) }
else
Spinner.start do
Spinner.status = "Fetching repos for #{Config.organization}..."
Organization.new(name: Config.organization).repos
.tap { Spinner.status = "Found #{_1.size} repositories." }
end
end
end
alias_method :load_repositories, :repositories

def pulls
# Load before we enter the next spinner so we do not end up nesting them
load_repositories

@@pulls ||= Spinner.start do
Spinner.status = "Fetching pull requests..."

WaitAllThrottled(repositories) { _1.pulls }
.tap { Spinner.status = "Found #{_1.size} pull requests." }
end
end
alias_method :load_pulls, :pulls

def reviews
load_pulls

@@reviews ||= Spinner.start do
Spinner.status = "Fetching reviews..."

WaitAllThrottled(pulls) { Reviews.for(pull: _1) }
.tap { Spinner.status = "Found #{_1.size} reviews.\n" }
end
end
delegate :start, to: Runner
end
62 changes: 62 additions & 0 deletions lib/code_review_leaderboard/runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require "async/wait_all_throttled"

require_relative "config"
require_relative "formatter"
require_relative "organization"
require_relative "pulls"
require_relative "repository"
require_relative "reviews"
require_relative "spinner"

module CodeReviewLeaderboard
class Runner
class << self
def start
new.start
end
end

def start
puts Formatter.new(reviews).to_table
end

private

def repositories
@repositories ||= if Config.repositories.present?
Config.repositories.map { Repository.new(name: _1) }
else
Spinner.start do
Spinner.status = "Fetching repos for #{Config.organization}..."
Organization.new(name: Config.organization).repos
.tap { Spinner.status = "Found #{_1.size} repositories." }
end
end
end
alias_method :load_repositories, :repositories

def pulls
# Load before we enter the next spinner so we do not end up nesting them
load_repositories

@pulls ||= Spinner.start do
Spinner.status = "Fetching pull requests..."

WaitAllThrottled(repositories) { _1.pulls }
.tap { Spinner.status = "Found #{_1.size} pull requests." }
end
end
alias_method :load_pulls, :pulls

def reviews
load_pulls

@reviews ||= Spinner.start do
Spinner.status = "Fetching reviews..."

WaitAllThrottled(pulls) { Reviews.for(pull: _1) }
.tap { Spinner.status = "Found #{_1.size} reviews.\n" }
end
end
end
end
22 changes: 21 additions & 1 deletion lib/code_review_leaderboard/spinner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,31 @@ module Spinner
def start
result = nil

Whirly.start(spinner: "dots", stop: "✔") do
Whirly.start(spinner: "dots", stop: "✔", **options) do
result = yield
end

result
end

private

# NOTE: For testing only
# Even when using rspec `expect {...}.to output`, output is not suppressed
def options
{
stream:,
non_tty: (ENV["RUBY_ENV"] == "test")
}
end

def stream
if ENV["RUBY_ENV"] == "test"
require "stringio"
StringIO.new
else
$stdout
end
end
end
end
14 changes: 0 additions & 14 deletions spec/code_review_leaderboard/reviews_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@
let(:repository) { CodeReviewLeaderboard::Repository.new(name: "rails/rails") }
let(:pull) { object_fixture("spec/fixtures/pull-208.json") }

before do
Timecop.freeze(Date.new(2024, 2, 8))

[208, 206].each do |number|
stub_request(:get, "https://api.github.com/repos/#{repository.name}/pulls/#{number}/reviews")
.with(query: hash_including({}))
.to_return_json(body: JSON.parse(File.read("spec/fixtures/reviews-#{number}.json")))
end
end

after do
Timecop.return
end

describe ".for" do
it "aggregates the reviews of a pull request" do
expect(described_class.for(pull:))
Expand Down
4 changes: 3 additions & 1 deletion spec/code_review_leaderboard/spinner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
it "shows the spinner" do
described_class.start { "result" }

expect(Whirly).to have_received(:start).with(spinner: "dots", stop: "✔")
expect(Whirly).to have_received(:start).with(
hash_including(spinner: "dots", stop: "✔")
)
end

it "returns the result of the block" do
Expand Down
133 changes: 132 additions & 1 deletion spec/code_review_leaderboard_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,137 @@

RSpec.describe CodeReviewLeaderboard do
it "has a version number" do
expect(CodeReviewLeaderboard::VERSION).not_to be nil
expect(CodeReviewLeaderboard::VERSION).to be_present
end

describe "#initialize!" do
before do
# Putting this in `after` sometimes does not seem to actually clear it
CodeReviewLeaderboard::Config.config.clear
end

it "initializes the configuration" do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with("ACCESS_TOKEN").and_return("token")
allow(ENV).to receive(:[]).with("REPOSITORY").and_return("rails/rails")

described_class.initialize!

expect(CodeReviewLeaderboard::Config.access_token).to eq("token")
end

it "throws an error if the access token is missing" do
expect { described_class.initialize! }
.to raise_error(CodeReviewLeaderboard::ConfigurationError)
end

it "throws an error if the repository and owner is missing" do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with("ACCESS_TOKEN").and_return("token")

expect { described_class.initialize! }
.to raise_error(CodeReviewLeaderboard::ConfigurationError)
end
end

describe "#start" do
before do
CodeReviewLeaderboard::Config.config.clear
CodeReviewLeaderboard::Config.access_token = "token"
end

context "with repository" do
let(:repository) { CodeReviewLeaderboard::Repository.new(name: "rails/rails") }

before do
CodeReviewLeaderboard::Config.repositories = [repository.name]

stub_request(:get, "https://api.github.com/repos/rails/rails/pulls")
.with(query: hash_including({}))
.to_return_json(
{body: json_fixture("spec/fixtures/pulls.json")},
{body: []}
)

stub_request(:get, "https://api.github.com/repos/rails/rails/pulls/208/reviews")
.with(query: hash_including({}))
.to_return_json(body: json_fixture("spec/fixtures/reviews-208.json"))

stub_request(:get, "https://api.github.com/repos/rails/rails/pulls/206/reviews")
.with(query: hash_including({}))
.to_return_json(body: json_fixture("spec/fixtures/reviews-206.json"))
end

it "prints the leaderboard" do
expect { described_class.start }
.to output(
<<~OUTPUT
+---------+-------+----------+-------------------+-----------+
| Login | Total | Approved | Changes Requested | Commented |
+---------+-------+----------+-------------------+-----------+
| octocat | 3 | 2 | 1 | 0 |
| defunkt | 1 | 0 | 0 | 1 |
+---------+-------+----------+-------------------+-----------+
OUTPUT
).to_stdout
end
end

context "with organization", :github_mock do
let(:organization) { CodeReviewLeaderboard::Organization.new(name: "rails") }

before do
CodeReviewLeaderboard::Config.organization = organization.name

stub_request(:get, "https://api.github.com/repos/rails/rails/pulls")
.with(query: hash_including({}))
.to_return_json(
{body: json_fixture("spec/fixtures/pulls.json")},
{body: []}
)

stub_request(:get, "https://api.github.com/repos/rails/thor/pulls")
.with(query: hash_including({}))
.to_return_json(
{body: json_fixture("spec/fixtures/pulls-2.json")},
{body: []}
)

stub_request(:get, "https://api.github.com/repos/rails/jbuilder/pulls")
.with(query: hash_including({}))
.to_return_json(body: [])

stub_request(:get, "https://api.github.com/repos/rails/rails/pulls/208/reviews")
.with(query: hash_including({}))
.to_return_json(body: json_fixture("spec/fixtures/reviews-208.json"))

stub_request(:get, "https://api.github.com/repos/rails/rails/pulls/206/reviews")
.with(query: hash_including({}))
.to_return_json(body: json_fixture("spec/fixtures/reviews-206.json"))

stub_request(:get, "https://api.github.com/repos/rails/thor/pulls/112/reviews")
.with(query: hash_including({}))
.to_return_json(body: json_fixture("spec/fixtures/reviews-112.json"))

stub_request(:get, "https://api.github.com/repos/rails/thor/pulls/110/reviews")
.with(query: hash_including({}))
.to_return_json(body: json_fixture("spec/fixtures/reviews-110.json"))
end

it "prints the leaderboard" do
expect { described_class.start }
.to output(
<<~OUTPUT
+-------------+-------+----------+-------------------+-----------+
| Login | Total | Approved | Changes Requested | Commented |
+-------------+-------+----------+-------------------+-----------+
| octocat | 4 | 2 | 1 | 1 |
| markokajzer | 2 | 2 | 0 | 0 |
| defunkt | 2 | 0 | 0 | 2 |
+-------------+-------+----------+-------------------+-----------+
OUTPUT
).to_stdout
end
end
end
end
10 changes: 10 additions & 0 deletions spec/fixtures/pulls-2.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
[
{
"number": 112,
"base": {
"repo": {
"full_name": "rails/thor"
}
},
"created_at": "2024-01-12"
},
{
"number": 110,
"base": {
"repo": {
"full_name": "rails/thor"
}
},
"created_at": "2024-01-10"
}
]
Loading
Loading