├── .rspec ├── .rvmrc ├── .gitignore ├── spec ├── spec_helper.rb ├── hackershout_spec.rb └── hackershout │ ├── provider │ └── base_spec.rb │ ├── provider_spec.rb │ └── base_spec.rb ├── lib ├── hackershout │ ├── version.rb │ ├── output.rb │ ├── provider │ │ ├── hackernews.rb │ │ ├── reddit.rb │ │ ├── rubyflow.rb │ │ └── base.rb │ ├── provider.rb │ └── base.rb └── hackershout.rb ├── bin └── hackershout ├── Gemfile ├── Rakefile ├── Guardfile ├── hackershout.gemspec └── Readme.md /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | -------------------------------------------------------------------------------- /.rvmrc: -------------------------------------------------------------------------------- 1 | rvm --create use ruby-1.9.2@hackershout 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | pkg/* 5 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rspec' 2 | require 'hackershout' 3 | -------------------------------------------------------------------------------- /lib/hackershout/version.rb: -------------------------------------------------------------------------------- 1 | module Hackershout 2 | VERSION = "0.2.0" 3 | end 4 | -------------------------------------------------------------------------------- /bin/hackershout: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | $: << 'lib' 3 | require 'hackershout' 4 | 5 | Hackershout.run 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in hackershout.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/hackershout/output.rb: -------------------------------------------------------------------------------- 1 | module Hackershout 2 | module Output 3 | 4 | def print(str) 5 | $stdout.print "\n" + str 6 | end 7 | 8 | def blank 9 | print "\n" 10 | end 11 | 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | require 'rspec/core' 5 | require 'rspec/core/rake_task' 6 | RSpec::Core::RakeTask.new(:spec) do |spec| 7 | spec.pattern = FileList['spec/**/*_spec.rb'] 8 | end 9 | 10 | task :default => :spec 11 | task :test => [:spec] 12 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # A sample Guardfile 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | guard 'rspec', :version => 2 do 5 | watch(/^spec\/(.*)_spec.rb/) 6 | watch(/^lib\/(.*)\.rb/) { |m| "spec/lib/#{m[1]}_spec.rb" } 7 | watch(/^spec\/spec_helper.rb/) { "spec" } 8 | end 9 | -------------------------------------------------------------------------------- /spec/hackershout_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Hackershout do 4 | 5 | describe ".run" do 6 | it 'calls run on a new Base instance' do 7 | Hackershout::Base.should_receive(:new).and_return(double(:base).tap { |b| 8 | b.should_receive(:run) 9 | }) 10 | subject.run 11 | end 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /lib/hackershout.rb: -------------------------------------------------------------------------------- 1 | require 'hackershout/output' 2 | require 'hackershout/provider' 3 | require 'hackershout/provider/base' 4 | require 'hackershout/provider/reddit' 5 | require 'hackershout/provider/hackernews' 6 | require 'hackershout/provider/rubyflow' 7 | require 'hackershout/base' 8 | 9 | module Hackershout 10 | class << self 11 | def run 12 | Base.new.run 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/hackershout/provider/hackernews.rb: -------------------------------------------------------------------------------- 1 | module Hackershout 2 | module Provider 3 | class Hackernews < Base 4 | 5 | URL = { 6 | :login => 'http://news.ycombinator.com/submit' 7 | } 8 | 9 | def post 10 | page = agent.get(URL[:login]) 11 | login_form = page.forms.first 12 | login_form.u = @login 13 | login_form.p = @password 14 | page = login_form.submit 15 | submit(page) 16 | end 17 | 18 | private 19 | 20 | def submit(submit_page) 21 | form = submit_page.forms.first 22 | form.t = @title 23 | form.u = @url 24 | form.submit 25 | end 26 | 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/hackershout/provider/reddit.rb: -------------------------------------------------------------------------------- 1 | module Hackershout 2 | module Provider 3 | class Reddit < Base 4 | 5 | URL = { 6 | :login => 'http://www.reddit.com/r/ruby/', 7 | :submit => 'http://www.reddit.com/r/ruby/submit', 8 | } 9 | 10 | # Not logging in! :( 11 | def post 12 | raise NotImplementedError 13 | page = agent.get(URL[:login]) 14 | login_form = page.forms_with(:action => 'http://www.reddit.com/r/ruby/post/login').first 15 | login_form.user = @login 16 | login_form.passwd = @password 17 | page = login_form.submit 18 | puts page.links_with(:text => 'logout').inspect 19 | page = page.links_with(:text => 'Submit a link').first.click 20 | puts page.inspect 21 | 22 | rescue Mechanize::ResponseCodeError=>e 23 | puts "#{@name} is unavailable for now. Please try in a few minutes. The server gave the following reason:" 24 | puts e.inspect 25 | end 26 | 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/hackershout/provider/rubyflow.rb: -------------------------------------------------------------------------------- 1 | module Hackershout 2 | module Provider 3 | class Rubyflow < Base 4 | 5 | URL = { 6 | :login => 'http://www.rubyflow.com/login' 7 | } 8 | 9 | def post 10 | page = agent.get(URL[:login]) 11 | login_form = page.form_with(:action => '/session') 12 | login_form.login = @login 13 | login_form.password = @password 14 | page = login_form.submit 15 | page = page.link_with(:href => /items\/new/).click 16 | submit(page) 17 | end 18 | 19 | private 20 | 21 | def submit(submit_page) 22 | form = submit_page.form_with(:action => '/items') 23 | form['item[title]'] = @title 24 | form['item[content]'] = process(@message) 25 | form.submit 26 | end 27 | 28 | def process(message) 29 | message.gsub!('', "") 30 | message.gsub!('', "") 31 | message 32 | end 33 | 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/hackershout/provider/base.rb: -------------------------------------------------------------------------------- 1 | require 'mechanize' 2 | require 'nokogiri' 3 | 4 | Mechanize.html_parser = Nokogiri::HTML 5 | 6 | module Hackershout 7 | module Provider 8 | class Base 9 | attr_reader :agent 10 | 11 | include Output 12 | 13 | def initialize(options = {}) 14 | @name = self.class.name.split("::").last 15 | @url = options[:url] << "&utm_medium=#{@name.downcase}" 16 | @title = options[:title] 17 | @tags = options[:tags] 18 | @message = options[:message] 19 | 20 | creds = YAML.load(File.read(File.join(File.expand_path('~'), '.hackershoutrc')))[@name.downcase] 21 | raise "Can't find credentials on ~/.hackershoutrc for #{@name}" unless creds 22 | 23 | @login = creds["login"] 24 | @password = creds["password"] 25 | @agent = Mechanize.new 26 | end 27 | 28 | def publish 29 | print "Posting to #{@name}..." 30 | post unless ENV['NOSEND'] 31 | print "Posted to #{@name}!" 32 | end 33 | 34 | def post 35 | raise NotImplementedError 36 | end 37 | 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /hackershout.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "hackershout/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "hackershout" 7 | s.version = Hackershout::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Josep M. Bach", "Josep Jaume Rey", "Oriol Gual"] 10 | s.email = ["info@codegram.com"] 11 | s.homepage = "http://github.com/codegram/hackershout" 12 | s.summary = %q{Shout your hackerness! Promote your work on Reddit, Hackernews and Ruby Flow.} 13 | s.description = %q{Shout your hackerness! Promote your work on Reddit, Hackernews and Ruby Flow.} 14 | 15 | s.rubyforge_project = "hackershout" 16 | 17 | s.add_runtime_dependency 'nokogiri' 18 | s.add_runtime_dependency 'mechanize' 19 | 20 | s.add_development_dependency 'rspec', '~> 2.5.0' 21 | s.add_development_dependency 'guard' 22 | s.add_development_dependency 'guard-rspec' 23 | s.add_development_dependency 'rb-fsevent' 24 | s.add_development_dependency 'vcr' 25 | 26 | s.files = `git ls-files`.split("\n") 27 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 28 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 29 | s.require_paths = ["lib"] 30 | end 31 | -------------------------------------------------------------------------------- /spec/hackershout/provider/base_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Hackershout 4 | module Provider 5 | describe Base do 6 | 7 | # Test only base class. Each provider only implements #post with pure Mechanize logic. 8 | 9 | before do 10 | File.stub(:read).and_return """ 11 | base: 12 | login: my.email@gmail.com 13 | password: mypassword 14 | """ 15 | end 16 | 17 | describe "#initialize" do 18 | it 'reads the credentials and stores them' do 19 | base = Base.new(:url => 'url', 20 | :tags => ['my', 'tags'], 21 | :message => 'message') 22 | 23 | base.instance_variable_get(:@login).should eq('my.email@gmail.com') 24 | base.instance_variable_get(:@password).should eq('mypassword') 25 | base.instance_variable_get(:@agent).should be_a(Mechanize) 26 | base.instance_variable_get(:@url).should == 'url&utm_medium=base' 27 | end 28 | end 29 | 30 | describe "#publish" do 31 | it 'logs in and posts' do 32 | base = Base.new(:url => 'url', 33 | :tags => ['my', 'tags'], 34 | :message => 'message') 35 | 36 | base.should_receive(:post) 37 | 38 | base.publish 39 | end 40 | end 41 | 42 | it 'crap' do 43 | File.stub(:read).and_return """ 44 | hackernews: 45 | login: codegram 46 | password: codgamerP90 47 | """ 48 | Hackernews.new(:title => 'my title', :message => 'my message', :url => 'http://google.com').post 49 | end 50 | 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/hackershout/provider.rb: -------------------------------------------------------------------------------- 1 | module Hackershout 2 | module Provider 3 | class << self 4 | 5 | include Output 6 | 7 | def list 8 | { 9 | # :reddit => 'Ruby Reddit', 10 | :hackernews => 'Hackernews', 11 | :rubyflow => 'RubyFlow', 12 | } 13 | end 14 | 15 | def wants?(provider) 16 | name = list[provider] 17 | print "\t#{name} (y/n)? " 18 | return case gets.chomp 19 | when 'y' 20 | check_credentials_for(provider) 21 | when 'n' 22 | false 23 | else 24 | blank 25 | print "I don't understand. Just type y for yes and n for no :)" 26 | wants?(provider) 27 | end 28 | end 29 | 30 | private 31 | 32 | def check_credentials_for(provider) 33 | credentials = if File.exists?(File.join(File.expand_path('~'), '.hackershoutrc')) 34 | YAML.load(File.read(File.join(File.expand_path('~'), '.hackershoutrc'))) 35 | else 36 | ask_for_credentials(provider) 37 | end 38 | 39 | if credentials[provider.to_s] && 40 | credentials[provider.to_s]["login"] && 41 | credentials[provider.to_s]["password"] 42 | true 43 | else 44 | ask_for_credentials(provider) 45 | end 46 | end 47 | 48 | def ask_for_credentials(provider) 49 | print "Sorry, I don't have your #{list[provider]} credentials." 50 | print "\tLogin: " 51 | login = gets.chomp.strip 52 | system('stty -echo') 53 | print "\tPassword: " 54 | password = gets.chomp.strip 55 | system('stty echo') 56 | File.open(File.join(File.expand_path('~'), '.hackershoutrc'), 'a') do |file| 57 | file.write "\n#{provider}:" 58 | file.write "\n login: #{login}" 59 | file.write "\n password: #{password}" 60 | file.write "\n" 61 | end 62 | { provider => { "login" => login, "password" => password } } 63 | end 64 | 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/hackershout/base.rb: -------------------------------------------------------------------------------- 1 | require 'hackershout/output' 2 | 3 | module Hackershout 4 | class Base 5 | include Output 6 | 7 | def initialize(options = {}) 8 | @url = options[:url] 9 | @title = options[:title] 10 | @message = options[:message] 11 | @tags = options[:tags] || [] 12 | @providers = options[:providers] || [] 13 | end 14 | 15 | def run 16 | welcome_banner 17 | @url = ask_for_url 18 | @title = ask_for_title 19 | @message = ask_for_message 20 | @tags = ask_for_tags 21 | providers_banner 22 | 23 | @providers = ask_for_providers 24 | post_to_providers 25 | end 26 | 27 | def welcome_banner 28 | print ":: Welcome to hackershout! ::" 29 | blank 30 | end 31 | 32 | def ask_for_url 33 | print "Type the URL you want to share: " 34 | gets.chomp.strip << "?utm_source=hackershout" 35 | end 36 | 37 | def ask_for_title 38 | print "Enter a brief, descriptive title: " 39 | gets.chomp.strip 40 | end 41 | 42 | def ask_for_message 43 | print "Bear in mind that some services may require a more extended text aside from the title." 44 | print "Type your message (two ENTERs to finish): " 45 | $/ = "\n\n" 46 | gets.chomp.strip.tap do 47 | # Restore EOM char 48 | $/ = "\n" 49 | end 50 | end 51 | 52 | def ask_for_tags 53 | print "Type some tags separated by comma (i.e. ruby, rails, bdd): " 54 | gets.chomp.strip.split(',').map(&:strip) 55 | end 56 | 57 | def providers_banner 58 | print "...Got it! Now where would you want to spread the word?" 59 | end 60 | 61 | def ask_for_providers 62 | Provider.list.keys.select do |provider| 63 | Provider.wants?(provider) 64 | end 65 | end 66 | 67 | def post_to_providers 68 | print "Fine." 69 | @providers.map do |provider| 70 | eval("Provider::#{provider.capitalize}").new({ 71 | url: @url, 72 | title: @title, 73 | message: @message, 74 | tags: @tags, 75 | }) 76 | end.each do |provider| 77 | provider.publish 78 | end 79 | puts "Done. Happy hacking! :)\n" 80 | end 81 | 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /spec/hackershout/provider_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Hackershout 4 | describe Provider do 5 | 6 | before do 7 | subject.stub(:list).and_return({ 8 | :reddit => 'Ruby Reddit', 9 | :hackernews => 'Hackernews', 10 | :rubyflow => 'RubyFlow', 11 | }) 12 | end 13 | 14 | describe "#wants?(provider)" do 15 | before do 16 | subject.should_receive(:print).with("\tRuby Reddit (y/n)? ") 17 | end 18 | context 'if the user wants to publish on a provider' do 19 | it 'checks the credentials' do 20 | subject.should_receive(:gets).and_return 'y' 21 | subject.should_receive(:check_credentials_for).with(:reddit) 22 | subject.wants?(:reddit) 23 | end 24 | end 25 | context 'if the user doesn\'t want' do 26 | it 'returns false' do 27 | subject.should_receive(:gets).and_return 'n' 28 | subject.wants?(:reddit).should be_false 29 | end 30 | end 31 | end 32 | 33 | describe "#check_credentials_for(provider)" do 34 | 35 | context 'if the credentials exist' do 36 | it 'returns true' do 37 | File.stub(:read).and_return "reddit:\n login: my.email@gmail.com\n password: mypassword" 38 | subject.should_not_receive(:ask_for_credentials) 39 | subject.send(:check_credentials_for, :reddit).should be_true 40 | end 41 | end 42 | 43 | context 'otherwise' do 44 | it 'asks for them' do 45 | File.stub(:read).and_return "hackernews:\n login: my.email@gmail.com\n password: mypassword" 46 | subject.should_receive(:ask_for_credentials).with(:reddit) 47 | subject.send(:check_credentials_for, :reddit) 48 | end 49 | end 50 | 51 | context "if the file doesn't even exist" do 52 | it 'asks for the credentials as well' do 53 | File.stub(:exists?).and_return false 54 | subject.should_receive(:ask_for_credentials).with(:reddit).and_return({"reddit" => {"login" => "login", "password" => "password"}}) 55 | subject.send(:check_credentials_for, :reddit) 56 | end 57 | end 58 | 59 | end 60 | 61 | describe "#ask_for_credentials(provider)" do 62 | it 'asks for the credentials and saves them into ~/.hackershoutrc' do 63 | subject.stub(:print) 64 | file = double :file 65 | subject.should_receive(:gets).and_return 'my.email@gmail.com' 66 | subject.should_receive(:gets).and_return 'mypassword' 67 | File.should_receive(:open).and_yield file 68 | 69 | file.should_receive(:write).with "\nreddit:" 70 | file.should_receive(:write).with "\n login: my.email@gmail.com" 71 | file.should_receive(:write).with "\n password: mypassword" 72 | file.should_receive(:write).with "\n" 73 | 74 | subject.send(:ask_for_credentials, :reddit) 75 | end 76 | end 77 | 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | #Hackershout 2 | 3 | Shout your hackerness to the world! 4 | 5 | Hackershout lets you promote your open-source work on the major Ruby (and geek 6 | related) community blogs (Reddit, Hackernews and RubyFlow) via a nice command 7 | line interface. 8 | 9 | ##Install 10 | 11 | $ gem install hackershout 12 | 13 | ##Known caveats 14 | 15 | Publishing to Reddit is not available yet. 16 | 17 | ##Notes 18 | 19 | Through hackershout you publish an **URL** and a **text**. To link the URL from 20 | the text you just have to use the special `` tag. Note that for certain 21 | sites, such as RubyFlow, you _have to link_ the URL from the text, since there 22 | is no separate URL field. Hackershout will omit the special tag where it 23 | doesn't need it (for example, in Reddit). 24 | 25 | You can add additional links with normal HTML `` tags. 26 | 27 | Given `http://rubygems.org/gems/my_gem` as an URL, an example of a message 28 | would be: 29 | 30 | Hey! I have released some awesome open-source gem that is 31 | going to save the world. Check it out! You can also grab the source code on 32 | Github if you want. 33 | 34 | This will publish in Reddit like this: 35 | 36 | URL: http://rubygems.org/gems/my_gem 37 | TEXT: Hey! I have released some awesome open-source gem that is going to 38 | save the world. Check it out! You can also grab the source code on 39 | Github if you want. 40 | 41 | And on RubyFlow (where there is no separate URL field) like this: 42 | 43 | TEXT: Hey! I have released some 44 | awesome open-source gem that is going to save the world. Check it out! 45 | You can also grab the source code on 46 | Github if you want. 47 | 48 | ##Usage 49 | 50 | $ hackershout 51 | 52 | :: Welcome to hackershout! :: 53 | 54 | Type the URL you want to share: http://rubygems.com/gems/my_gem 55 | Enter a brief, descriptive title: Released MyGem 1.0! 56 | 57 | Bear in mind that some services may require a more extended text aside from the title. 58 | Type your message (two ENTERs to finish): 59 | Hey! I have released some awesome open-source gem that is 60 | going to save the world. Check it out! You can also grab the source code 61 | on Github if you want.(enter) 62 | (enter) 63 | Type some tags separated by comma (i.e. ruby, rails, bdd): ruby, parsing 64 | 65 | ...Got it! Now where would you want to spread the word? 66 | Ruby Reddit (y/n)? y 67 | Sorry, I don't have your Ruby Reddit credentials. 68 | E-mail: my.email@gmail.com 69 | Password: ******** 70 | Saved! You won't have to enter your credentials for Ruby Reddit again. 71 | Hackernews (y/n)? y 72 | RubyFlow (y/n)? n 73 | Fine. 74 | Posting to Ruby Reddit...........ok 75 | Posting to Hackernews............ok 76 | 77 | Done. Happy hacking! :) 78 | 79 | ##Contribute! 80 | 81 | * Fork the project. 82 | * Make your feature addition or bug fix. 83 | * Add specs for it. This is important so I don't break it in a future 84 | version unintentionally. 85 | * Commit, do not mess with rakefile, version, or history. 86 | If you want to have your own version, that is fine but bump version 87 | in a commit by itself I can ignore when I pull. 88 | * Send me a pull request. Bonus points for topic branches. 89 | 90 | ## Copyright 91 | 92 | Copyright (c) 2011 Codegram. See LICENSE for details. 93 | -------------------------------------------------------------------------------- /spec/hackershout/base_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Hackershout 4 | describe Base do 5 | 6 | describe ".run" do 7 | before do 8 | subject.stub(:welcome_banner) 9 | subject.stub(:ask_for_url) 10 | subject.stub(:ask_for_message) 11 | subject.stub(:ask_for_title) 12 | subject.stub(:ask_for_tags) 13 | subject.stub(:providers_banner) 14 | subject.stub(:ask_for_providers) 15 | subject.stub(:post_to_providers) 16 | end 17 | it 'calls welcome banner' do 18 | subject.should_receive(:welcome_banner) 19 | subject.run 20 | end 21 | it 'calls ask_for_url' do 22 | subject.should_receive(:ask_for_url) 23 | subject.run 24 | end 25 | it 'calls ask_for_title' do 26 | subject.should_receive(:ask_for_title) 27 | subject.run 28 | end 29 | it 'calls ask_for_message' do 30 | subject.should_receive(:ask_for_message) 31 | subject.run 32 | end 33 | it 'calls ask_for_tags' do 34 | subject.should_receive(:ask_for_tags) 35 | subject.run 36 | end 37 | it 'calls providers_banner' do 38 | subject.should_receive(:providers_banner) 39 | subject.run 40 | end 41 | it 'calls ask_for_providers' do 42 | subject.should_receive(:ask_for_providers) 43 | subject.run 44 | end 45 | end 46 | 47 | describe "#welcome_banner" do 48 | it 'prints the welcome banner' do 49 | subject.should_receive(:blank).any_number_of_times 50 | subject.should_receive(:print).with(":: Welcome to hackershout! ::") 51 | subject.welcome_banner 52 | end 53 | end 54 | 55 | describe "#ask_for_url" do 56 | it 'asks for the url and returns it with appended metainformation' do 57 | subject.should_receive(:print).with("Type the URL you want to share: ") 58 | subject.should_receive(:gets).and_return ' http://rubygems.org/gems/my_gem ' 59 | subject.ask_for_url.should == 'http://rubygems.org/gems/my_gem?utm_source=hackershout' 60 | end 61 | end 62 | 63 | describe "#ask_for_title" do 64 | it 'asks for the title and returns it' do 65 | subject.should_receive(:print).with("Enter a brief, descriptive title: ") 66 | subject.should_receive(:gets).and_return ' Released my gem: a nifty gem to eradicate hunger! ' 67 | subject.ask_for_title.should == 'Released my gem: a nifty gem to eradicate hunger!' 68 | end 69 | end 70 | 71 | describe "#ask_for_message" do 72 | it 'asks for the message and returns it' do 73 | subject.should_receive(:print).with("Bear in mind that some services may require a more extended text aside from the title.") 74 | subject.should_receive(:print).with("Type your message (two ENTERs to finish): ") 75 | subject.should_receive(:gets).and_return(""" 76 | Hey! I have released some awesome open-source gem that is 77 | going to save the world.\nCheck it out! You can also grab the source code 78 | on Github if you want. 79 | 80 | """) 81 | subject.ask_for_message 82 | end 83 | end 84 | 85 | describe "#ask_for_tags" do 86 | it 'asks for the tags and returns them' do 87 | subject.should_receive(:print).with("Type some tags separated by comma (i.e. ruby, rails, bdd): ") 88 | subject.should_receive(:gets).and_return ' ruby , bdd, rails, parsing ' 89 | subject.ask_for_tags.should == %w( ruby bdd rails parsing ) 90 | end 91 | end 92 | 93 | describe "#providers_banner" do 94 | it 'prints the providers banner' do 95 | subject.should_receive(:print).with("...Got it! Now where would you want to spread the word?") 96 | subject.providers_banner 97 | end 98 | end 99 | 100 | describe "#ask_for_providers" do 101 | it 'asks for providers' do 102 | providers = [:reddit, :hackernews, :rubyflow] 103 | Provider.stub_chain('list.keys').and_return providers 104 | Provider.should_receive(:wants?).with(:reddit).and_return true 105 | Provider.should_receive(:wants?).with(:hackernews).and_return false 106 | Provider.should_receive(:wants?).with(:rubyflow).and_return true 107 | 108 | subject.ask_for_providers.should == [:reddit, :rubyflow] 109 | end 110 | end 111 | 112 | describe "#post_to_providers" do 113 | it 'instantiates each provider and calls #publish on it' do 114 | args = { 115 | :url => 'http://rubygems.org/gems/my_gem', 116 | :title => 'Released MyGem!', 117 | :tags => ['ruby', 'bdd'], 118 | :message => 'Hello!', 119 | } 120 | base = Base.new({:providers => [:reddit, :hackernews]}.update(args)) 121 | base.stub(:print) 122 | 123 | hackernews = double :provider 124 | reddit = double :provider 125 | 126 | Provider::Hackernews.should_receive(:new).with(args).and_return hackernews 127 | Provider::Reddit.should_receive(:new).with(args).and_return reddit 128 | 129 | hackernews.should_receive(:publish) 130 | reddit.should_receive(:publish) 131 | 132 | base.post_to_providers 133 | end 134 | end 135 | 136 | end 137 | end 138 | --------------------------------------------------------------------------------