stars 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Zach Holman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,45 @@
1
+ # stars
2
+ ### you're so vain / you probably think these stars are about you
3
+
4
+ ## why
5
+
6
+ [Favstar](http://favstar.fm) is about opening another line of dialogue between you and your Twitter followers. Like the one where someone likes what you tweet but is too nervous to tell you to your face and they star your tweets instead, so instead you shake them down in the kitchen after a long tequila bender and steal their precious stars and keep them for yourself.
7
+
8
+ So anyway, I spend a lot of time on the command line, and switching over to the browser just to view [my stars](http://favstar.fm/users/holman) is so passé.
9
+
10
+ ## how
11
+
12
+ Install with `gem install stars`, then do a quick `stars`, fill in your Twitter username, and let it do its sultry magic. This is me lately:
13
+
14
+ +-------+-------------+--------------------------------------------------------+
15
+ | Stars | Time | Your Funnies |
16
+ +-------+-------------+--------------------------------------------------------+
17
+ | * | 10 days ago | "Any Flash developers I meet I try to arrange their... |
18
+ | * * | 10 days ago | Why doesn't digg do fulltext RSS feeds on their dev... |
19
+ | * | 10 days ago | I can't wait until the US relaxes its patent system... |
20
+ | * | 9 days ago | If this happens to be Twitter's 10,000,000,000th tw... |
21
+ | * | 8 days ago | Are any of you ladies from my dreams? No really, i... |
22
+ | * * | 7 days ago | I have a severe sore throat. Or, if I said that ou... |
23
+ | * * | 7 days ago | Way too many Scientology ads on Muni buses. It wor... |
24
+ | * | 7 days ago | Napping didn't fix this cold; I feel a bit worse. M... |
25
+ | * | 6 days ago | God I leave the room for one minute and the girls o... |
26
+ | * | 6 days ago | Man, Avatar really fucked Up. |
27
+ | * | 5 days ago | I'd play out here, but the west coast is all about ... |
28
+ | * | 5 days ago | I just want to know who moved my Maps app to my iPh... |
29
+ | * | 5 days ago | just about finished my thesis on generating free en... |
30
+ | * * | 3 days ago | You change your Facebook pic, that syncs to my iPho... |
31
+ | * | 2 days ago | Going to totally refork and rework my dotfiles soon... |
32
+ | * | 2 days ago | Oh hey, a year or so of my beer consumption: http:/... |
33
+ | * | 1 day ago | In another life I want to be a pop star heartthrob ... |
34
+ | * * | 1 day ago | I pre-ordered an iPad, checked into lunch, and now ... |
35
+ +-------+-------------+--------------------------------------------------------+
36
+
37
+ You can tell from the relative dearth of stars that I'm in my *screw followers I'm important so here's what I had for lunch* phase. Don't worry; I'll become a star whore again and tweet pop culture references in relation to presidential penile size soon enough.
38
+
39
+ ## state of affairs
40
+
41
+ This was a one-night hack thing; ideally it'd be cool to allow some username switching, maybe retain some "this was read" state, and improve the formatting (if only "★" worked better in a fixed-width environment, AMIRITE?). All in due time. I mean, for you to fork and do it yourself, I mean.
42
+
43
+ ## who
44
+
45
+ [@holman](http://twitter.com/holman) did this. Follow me and star my stuff incessantly so we can prove to Dean Allen that stars are as important as currency, much [to his logically-argued dismay](http://favrd.textism.com/).
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "stars"
8
+ gem.summary = %Q{Recent favstar faves on your command line}
9
+ gem.description = %Q{Recent favstar faves on your command line.}
10
+ gem.email = "github.com@zachholman.com"
11
+ gem.homepage = "http://github.com/holman/stars"
12
+ gem.authors = ["Zach Holman"]
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ gem.add_dependency('httparty')
15
+ gem.add_dependency('terminal-table')
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "stars #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/stars ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
6
+
7
+ require 'stars'
8
+
9
+ Stars::Client.load!
@@ -0,0 +1,32 @@
1
+ module Stars
2
+ class Client
3
+
4
+ def self.load!
5
+ favstar = Stars::Favstar.new(username)
6
+ puts Stars::Formatter.new(favstar.recent)
7
+ end
8
+
9
+ def self.username
10
+ File.exists?(config_path) ? File.read(config_path) : prompt_for_username
11
+ end
12
+
13
+ def self.prompt_for_username
14
+ puts ""
15
+ puts ""
16
+ puts " ★ stars."
17
+ puts ""
18
+ puts "Type your Twitter username:"
19
+ remember_username(gets.chomp)
20
+ end
21
+
22
+ def self.remember_username(username)
23
+ File.open(config_path, 'w') {|f| f.write(username) }
24
+ username
25
+ end
26
+
27
+ def self.config_path
28
+ File.join(ENV['HOME'], '.stars')
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ module Stars
2
+ class Favstar
3
+ include HTTParty
4
+ base_uri 'favstar.fm'
5
+ format :xml
6
+ attr_accessor :username
7
+
8
+ def initialize(username)
9
+ @username = username
10
+ end
11
+
12
+ def recent
13
+ self.class.get("/users/#{@username}/rss")['rss']['channel']['item']
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,70 @@
1
+ require 'terminal-table/import'
2
+
3
+ module Stars
4
+ class Formatter
5
+
6
+ attr_accessor :tweets
7
+
8
+ def initialize(tweets)
9
+ @tweets = tweets
10
+ end
11
+
12
+ # I hate clients that don't retain line breaks, but in this case I'm boss.
13
+ def trim(text)
14
+ truncated = text.gsub("\n"," ")[0..50]
15
+ truncated + (truncated.size == text.size ? '' : '...')
16
+ end
17
+
18
+ def format(tweet)
19
+ stars,text = split_stars(tweet['title'])
20
+ [stars,relative_time(tweet['pubDate']),text]
21
+ end
22
+
23
+ def split_stars(text)
24
+ stars = text.match(/[\d+]./)[0].to_i
25
+ strip_point = text.index(':') + 2
26
+ text = text[strip_point..text.size]
27
+ [characterize(stars),trim(text)]
28
+ end
29
+
30
+ def characterize(number)
31
+ if number > 5
32
+ "* x #{number}"
33
+ else
34
+ number.times.collect{'*'}.join(' ')
35
+ end
36
+ end
37
+
38
+ def line_break
39
+ "\n"
40
+ end
41
+
42
+ def to_s
43
+ tweets = @tweets.reverse.collect{|tweet| format tweet}
44
+ table(['Stars','Time','Your Funnies'], *tweets).render
45
+ end
46
+
47
+ def relative_time(time)
48
+ post_date = Time.parse(time)
49
+ timespan = Time.now - Time.parse(time)
50
+
51
+ case timespan
52
+ when 0..59
53
+ "just now"
54
+ when 60..(3600-1)
55
+ "#{pluralize((timespan/60).to_i, 'minute', 'minutes')} ago"
56
+ when 3600..(3600*24-1)
57
+ "#{pluralize((timespan/3600).to_i, 'hour', 'hours')} ago"
58
+ when (3600*24)..(3600*24*30)
59
+ "#{pluralize((timespan/(3600*24)).to_i, 'day', 'days')} ago"
60
+ else
61
+ post_date.strftime("%m/%d/%Y")
62
+ end
63
+ end
64
+
65
+ # ActiveSupport pluralize
66
+ def pluralize(count, singular, plural = nil)
67
+ "#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize))
68
+ end
69
+ end
70
+ end
data/lib/stars.rb ADDED
@@ -0,0 +1,8 @@
1
+ module Stars ; end
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/stars')
4
+
5
+ require 'httparty'
6
+ require 'client'
7
+ require 'favstar'
8
+ require 'formatter'
data/stars.gemspec ADDED
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{stars}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Zach Holman"]
12
+ s.date = %q{2010-03-14}
13
+ s.default_executable = %q{stars}
14
+ s.description = %q{Recent favstar faves on your command line.}
15
+ s.email = %q{github.com@zachholman.com}
16
+ s.executables = ["stars"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.markdown"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.markdown",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/stars",
29
+ "lib/stars.rb",
30
+ "lib/stars/client.rb",
31
+ "lib/stars/favstar.rb",
32
+ "lib/stars/formatter.rb",
33
+ "stars.gemspec",
34
+ "test/helper.rb",
35
+ "test/test_client.rb",
36
+ "test/test_favstar.rb",
37
+ "test/test_formatter.rb",
38
+ "test/test_stars.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/holman/stars}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.6}
44
+ s.summary = %q{Recent favstar faves on your command line}
45
+ s.test_files = [
46
+ "test/helper.rb",
47
+ "test/test_client.rb",
48
+ "test/test_favstar.rb",
49
+ "test/test_formatter.rb",
50
+ "test/test_stars.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
58
+ s.add_runtime_dependency(%q<httparty>, [">= 0"])
59
+ s.add_runtime_dependency(%q<terminal-table>, [">= 0"])
60
+ else
61
+ s.add_dependency(%q<httparty>, [">= 0"])
62
+ s.add_dependency(%q<terminal-table>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<httparty>, [">= 0"])
66
+ s.add_dependency(%q<terminal-table>, [">= 0"])
67
+ end
68
+ end
69
+
data/test/helper.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'redgreen'
4
+ require 'rr'
5
+
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ require 'stars'
9
+
10
+ class Test::Unit::TestCase
11
+
12
+ include RR::Adapters::TestUnit
13
+
14
+ def favstar_tweet_hash
15
+ [
16
+ {
17
+ "title"=>"2 stars: I pre-ordered an iPad, checked into lunch, and now you want me to follow someone just because it's Friday? I CAN'T KEEP UP WITH YOU GUYS",
18
+ "pubDate"=>"Fri, 12 Mar 2010 20:43:40 +0000",
19
+ "guid"=>"http://favstar.fm/users/holman/status/10389110831?2",
20
+ "description"=>"Has been faved by 2 people<br /><br /><a href=\"http://favstar.fm/users/holman/status/10389110831\">This tweet</a>
21
+ &nbsp;&nbsp;&nbsp;<a href=\"http://favstar.fm/users/holman/recent\">All Recent</a>",
22
+ "link"=>"http://favstar.fm/users/holman/status/10389110831"
23
+ },
24
+ {
25
+ "title"=>"1 star: In another life I want to be a pop star heartthrob who also codes Perl in his free time. That'll confuse those impressionable teen fangirls.",
26
+ "pubDate"=>"Fri, 12 Mar 2010 20:13:46 +0000",
27
+ "guid"=>"http://favstar.fm/users/holman/status/10387998839?1",
28
+ "description"=>"Has been faved by 1 person<br /><br /><a href=\"http://favstar.fm/users/holman/status/10387998839\">This tweet</a>
29
+ &nbsp;&nbsp;&nbsp;<a href=\"http://favstar.fm/users/holman/recent\">All Recent</a>",
30
+ "link"=>"http://favstar.fm/users/holman/status/10387998839"
31
+ }
32
+ ]
33
+ end
34
+
35
+ end
@@ -0,0 +1,31 @@
1
+ require 'helper'
2
+
3
+ class TestClient < Test::Unit::TestCase
4
+
5
+ def test_load
6
+ mock(Stars::Formatter).new.with_any_args
7
+ mock(Stars::Client).puts.with_any_args
8
+ Stars::Client.load!
9
+ end
10
+
11
+ def test_username_when_exists
12
+ mock(File).exists?.with_any_args.returns(true)
13
+ mock(File).read.with_any_args
14
+ Stars::Client.username
15
+ end
16
+
17
+ def test_username_when_nonexistant
18
+ mock(File).exists?.with_any_args.returns(false)
19
+ mock(Stars::Client).prompt_for_username
20
+ Stars::Client.username
21
+ end
22
+
23
+ def test_write_home_config
24
+ assert_equal Stars::Client.remember_username('holman'), 'holman'
25
+ end
26
+
27
+ def test_config_path
28
+ assert Stars::Client.config_path.index('.stars')
29
+ end
30
+
31
+ end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ class TestFavstar < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @favstar = Stars::Favstar.new('holman')
7
+ end
8
+
9
+ def test_sets_username
10
+ assert_equal @favstar.username, 'holman'
11
+ end
12
+
13
+ def test_parties_hard
14
+ mock(Stars::Favstar).get('/users/holman/rss') {
15
+ {'rss' => {'channel' => {'item' => 'etc'} } }
16
+ }
17
+ @favstar.recent
18
+ end
19
+
20
+ end
@@ -0,0 +1,66 @@
1
+ require 'helper'
2
+
3
+ class TestFormatter < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @formatter = Stars::Formatter.new(favstar_tweet_hash)
7
+ end
8
+
9
+ def test_trim_breaks
10
+ tweet = "Line breaks\nare for lovers"
11
+ assert_equal @formatter.trim(tweet), 'Line breaks are for lovers'
12
+ end
13
+
14
+ def test_trim_length
15
+ tweet = "This is a tweet that is long enough to certainly "+
16
+ "need at least SOME truncating lol lol sigh."
17
+ assert_equal @formatter.trim(tweet),
18
+ 'This is a tweet that is long enough to certainly ne...'
19
+ end
20
+
21
+ def test_format
22
+ format = @formatter.format(favstar_tweet_hash[0])
23
+ assert_equal format.size, 3
24
+ assert_equal format[0], '* *'
25
+ end
26
+
27
+ def test_split_stars
28
+ tweet = "12 stars: A short tweet. Hey, a number: 5."
29
+ assert_equal @formatter.split_stars(tweet),
30
+ ['* x 12', 'A short tweet. Hey, a number: 5.']
31
+ end
32
+
33
+ def test_characterize_with_lots_of_stars
34
+ assert_equal @formatter.characterize(12),
35
+ '* x 12'
36
+ end
37
+
38
+ def test_characterize_with_a_few_stars
39
+ assert_equal @formatter.characterize(4),
40
+ '* * * *'
41
+ end
42
+
43
+ def test_line_break
44
+ assert_equal @formatter.line_break, "\n"
45
+ end
46
+
47
+ def test_to_s
48
+ # just make sure it doesn't blow up for now
49
+ @formatter.to_s
50
+ end
51
+
52
+ def test_relative_time
53
+ assert_equal @formatter.relative_time((Time.now - 2).to_s),
54
+ "just now"
55
+ assert_equal @formatter.relative_time((Time.now - 360).to_s),
56
+ "6 minutes ago"
57
+ assert_equal @formatter.relative_time((Time.now - 10000).to_s),
58
+ "2 hours ago"
59
+ end
60
+
61
+ def test_pluralizer
62
+ assert_equal @formatter.pluralize(1, 'day', 'day'), '1 day'
63
+ assert_equal @formatter.pluralize(2, 'day', 'days'), '2 days'
64
+ end
65
+
66
+ end
@@ -0,0 +1,9 @@
1
+ require 'helper'
2
+
3
+ class TestStars < Test::Unit::TestCase
4
+
5
+ def test_model
6
+ assert defined?(Stars)
7
+ end
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stars
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Zach Holman
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-14 00:00:00 -08:00
18
+ default_executable: stars
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: httparty
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: terminal-table
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :runtime
43
+ version_requirements: *id002
44
+ description: Recent favstar faves on your command line.
45
+ email: github.com@zachholman.com
46
+ executables:
47
+ - stars
48
+ extensions: []
49
+
50
+ extra_rdoc_files:
51
+ - LICENSE
52
+ - README.markdown
53
+ files:
54
+ - .document
55
+ - .gitignore
56
+ - LICENSE
57
+ - README.markdown
58
+ - Rakefile
59
+ - VERSION
60
+ - bin/stars
61
+ - lib/stars.rb
62
+ - lib/stars/client.rb
63
+ - lib/stars/favstar.rb
64
+ - lib/stars/formatter.rb
65
+ - stars.gemspec
66
+ - test/helper.rb
67
+ - test/test_client.rb
68
+ - test/test_favstar.rb
69
+ - test/test_formatter.rb
70
+ - test/test_stars.rb
71
+ has_rdoc: true
72
+ homepage: http://github.com/holman/stars
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options:
77
+ - --charset=UTF-8
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirements: []
95
+
96
+ rubyforge_project:
97
+ rubygems_version: 1.3.6
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Recent favstar faves on your command line
101
+ test_files:
102
+ - test/helper.rb
103
+ - test/test_client.rb
104
+ - test/test_favstar.rb
105
+ - test/test_formatter.rb
106
+ - test/test_stars.rb