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

DRAFT: Adds web command #1

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0c3cef7
Add command web
MatheusRich Jun 3, 2019
bc1514e
Remove gem-web dependencies
MatheusRich Jun 10, 2019
6fd06cc
Fix command web tests
MatheusRich Jun 10, 2019
0894ae6
Fix linter errors
MatheusRich Jun 11, 2019
28d1fc6
Remove launchy
MatheusRich Jun 11, 2019
c77e71d
Remove fixtures
MatheusRich Jun 11, 2019
3d43e79
Update Manifest.txt
MatheusRich Jun 11, 2019
a894c04
Make open browser command cross-platform
MatheusRich Jun 18, 2019
f68b1d7
Adds open browser commands
MatheusRich Jun 30, 2019
7a2507c
Change open browser command hash to method
MatheusRich Jul 7, 2019
290f241
Updates open default browser commands
MatheusRich Jul 7, 2019
ff8ed2b
Add test to web command when platform is unsupported
MatheusRich Jul 13, 2019
99722d8
Add tests for all platforms
MatheusRich Jul 15, 2019
0dd4f1a
Update usage on web command
MatheusRich Jul 15, 2019
0c4266b
Fix rubocop issues
MatheusRich Jul 15, 2019
c70106a
Update web command behavior
MatheusRich Jul 20, 2019
52e35ff
Fix web command tests
MatheusRich Jul 22, 2019
22f959d
Remove github and rubytoolbox options from web command
MatheusRich Aug 3, 2019
d7656a1
Remove API call from web command
MatheusRich Aug 3, 2019
b0752dc
Support only some info from metadata
MatheusRich Aug 6, 2019
467205c
Refactor web command executor
MatheusRich Aug 8, 2019
c9e19cd
Add API fallback to web command
MatheusRich Aug 13, 2019
5b1481a
Remove attr acessor from web command
MatheusRich Aug 14, 2019
ccd6053
Remove some useless code
MatheusRich Aug 18, 2019
c40739b
Add minor refactoring
MatheusRich Aug 19, 2019
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
3 changes: 3 additions & 0 deletions Manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ lib/rubygems/commands/stale_command.rb
lib/rubygems/commands/uninstall_command.rb
lib/rubygems/commands/unpack_command.rb
lib/rubygems/commands/update_command.rb
lib/rubygems/commands/web_command.rb
lib/rubygems/commands/which_command.rb
lib/rubygems/commands/yank_command.rb
lib/rubygems/compatibility.rb
Expand All @@ -320,6 +321,7 @@ lib/rubygems/deprecate.rb
lib/rubygems/doctor.rb
lib/rubygems/errors.rb
lib/rubygems/exceptions.rb
lib/rubygems/executor.rb
lib/rubygems/ext.rb
lib/rubygems/ext/build_error.rb
lib/rubygems/ext/builder.rb
Expand Down Expand Up @@ -544,6 +546,7 @@ test/rubygems/test_gem_commands_stale_command.rb
test/rubygems/test_gem_commands_uninstall_command.rb
test/rubygems/test_gem_commands_unpack_command.rb
test/rubygems/test_gem_commands_update_command.rb
test/rubygems/test_gem_commands_web_command.rb
test/rubygems/test_gem_commands_which_command.rb
test/rubygems/test_gem_commands_yank_command.rb
test/rubygems/test_gem_config_file.rb
Expand Down
1 change: 1 addition & 0 deletions lib/rubygems/command_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Gem::CommandManager
:uninstall,
:unpack,
:update,
:web,
:which,
:yank,
].freeze
Expand Down
38 changes: 38 additions & 0 deletions lib/rubygems/commands/web_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'rubygems/command'
require 'rubygems/executor'

class Gem::Commands::WebCommand < Gem::Command

def initialize
super "web", "Open the gem's homepage",
:command => nil,
:version => Gem::Requirement.default,
:latest => false

add_option("-c", "--sourcecode", "Open source code for the gem") do |v|
options[:sourcecode] = v
end
add_option("-d", "--doc", "Open documentation for the gem") do |v|
options[:doc] = v
end
add_option("-r", "--rubygems", "Open the rubygems.org page for the gem") do |v|
options[:rubygems] = v
end

@executor = Gem::Web::Executor.new
end

def arguments
"GEMNAME gem to open the webpage for"
end

def usage
"#{program_name} GEMNAME"
end

def execute
@executor.open_page(get_one_optional_argument, options)
end

end
65 changes: 65 additions & 0 deletions lib/rubygems/executor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true
require 'open-uri'
require 'json'

module Gem
module Web
class Executor

def open_page(gem, options)
begin
spec = Gem::Specification.find_by_name(gem)
rescue Gem::MissingSpecError => e
spec = fetch_remote_spec(gem)

if spec.nil?
puts "Could not find '#{gem}' in rubygems.org."
return
end
end

if options[:sourcecode]
get_info_from_metadata(spec, "source_code_uri")
elsif options[:doc]
get_info_from_metadata(spec, "documentation_uri")
elsif options[:rubygems]
open_rubygems(gem)
else
open_browser(spec.homepage)
end
end

def fetch_remote_spec(gem)
dep = Gem::Dependency.new(gem)
found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency(dep)
spec_tuple = found.first

spec_tuple.first unless spec_tuple.nil? || spec_tuple.empty?
end

def get_info_from_metadata(spec, info)
uri = spec.metadata[info]&.strip

if uri.nil? || uri.empty?
puts "Gem '#{spec.name}' does not specify #{info}."
else
open_browser(uri)
end
end

def open_rubygems(gem)
open_browser("https://rubygems.org/gems/#{gem}")
end

def open_browser(uri)
browser = ENV["BROWSER"]
if browser.nil? || browser.empty?
puts uri
else
system(browser, uri)
end
end

end
end
end
163 changes: 163 additions & 0 deletions test/rubygems/test_gem_commands_web_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# frozen_string_literal: true
require 'rubygems/test_case'
require 'rubygems/executor'
require 'rubygems/commands/web_command'

class TestGemCommandsWebCommand < Gem::TestCase

def setup
super
@cmd = Gem::Commands::WebCommand.new
@mock = MiniTest::Mock.new
ENV['BROWSER'] = nil
@gem = "bestgemever"
end

def test_default_option_should_be_homepage
@mock.expect(:homepage, "https://bestgemever.example.io")
Gem::Specification.stub :find_by_name, @mock do
assert_output("https://bestgemever.example.io\n") do
@cmd.handle_options [@gem]
@cmd.execute
end
end
@mock.verify
end

def test_open_the_documentation
metadata = {
"documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
}
@mock.expect(:metadata, metadata)

Gem::Specification.stub :find_by_name, @mock do
assert_output("https://www.example.info/gems/bestgemever/0.0.1\n") do
@cmd.handle_options ["-d", @gem]
@cmd.execute
end
end
@mock.verify
end

def test_open_the_source_code
metadata = {
"source_code_uri" => "https://example.com/user/bestgemever"
}
@mock.expect(:metadata, metadata)

Gem::Specification.stub :find_by_name, @mock do
assert_output("https://example.com/user/bestgemever\n") do
@cmd.handle_options ["-c", @gem]
@cmd.execute
end
end
@mock.verify
end

def test_open_when_info_is_missing
[["-c", "source_code_uri"], ["-d", "documentation_uri"]].each do |test_case|
option = test_case[0]
info = test_case[1]
@mock.expect(:metadata, {})
@mock.expect(:name, @gem)

Gem::Specification.stub :find_by_name, @mock do
assert_output("Gem '#{@gem}' does not specify #{info}.\n") do
@cmd.handle_options [option, @gem]
@cmd.execute
end
end
@mock.verify
end
end

def test_open_rubygems
Gem::Specification.stub :find_by_name, @mock do
assert_output("https://rubygems.org/gems/#{@gem}\n") do
@cmd.handle_options ["-r", @gem]
@cmd.execute
end
end
@mock.verify
end

def test_search_unexisting_gem
gem = "this-is-an-unexisting-gem"
assert_output(/Could not find '#{gem}'/) do
@cmd.handle_options [gem]
@cmd.execute
end
end

def test_search_online_if_gem_is_not_installed
gem = "this-is-an-unexisting-gem"
exception = proc { raise Gem::MissingSpecError.new("error", nil) }

Gem::Specification.stub :find_by_name, exception do
spec = util_spec(@gem)
found_spec = [[[spec, "sources"]], []]

Gem::SpecFetcher.fetcher.stub :spec_for_dependency, found_spec do
assert_output(/#{spec.homepage}/) do
@cmd.handle_options [gem]
@cmd.execute
end
end
end
end

def test_search_online_for_inexisting_gem
gem = "this-is-an-unexisting-gem"
exception = proc { raise Gem::MissingSpecError.new("error", nil) }

Gem::Specification.stub :find_by_name, exception, [gem] do
not_found = [[], []]
Gem::SpecFetcher.fetcher.stub :spec_for_dependency, not_found do
assert_output(/Could not find '#{gem}' in rubygems.org/) do
@cmd.handle_options [gem]
@cmd.execute
end
end
end
end

def test_fetch_remote_spec
found_spec = [[[util_spec(@gem), "sources"]], []]

Gem::SpecFetcher.fetcher.stub :spec_for_dependency, found_spec do
spec = Gem::Web::Executor.new.fetch_remote_spec @gem
assert_equal @gem, spec.name
end
end

def test_fetch_unexisting_remote_spec
gem = "this-is-an-unexisting-gem"
not_found = [[], []]

Gem::SpecFetcher.fetcher.stub :spec_for_dependency, not_found do
assert_nil Gem::Web::Executor.new.fetch_remote_spec gem
end
end

def test_open_browser_if_env_variable_is_set
open_browser_cmd = "open"
uri = "http://github.com/rails"

env_mock = MiniTest::Mock.new
env_mock.expect(:call, open_browser_cmd, ['BROWSER'])

browser_mock = MiniTest::Mock.new
browser_mock.expect(:call, true, [open_browser_cmd, uri])

executor = Gem::Web::Executor.new
ENV.stub :[], env_mock do
executor.stub :system, browser_mock do
executor.open_browser(uri)
end
end

browser_mock.verify
env_mock.verify
end

end