geeklets 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,22 @@
1
+ === 0.0.7
2
+ * updated WMATA_Alerts to use configurable values
3
+ * updated VRE_Alerts to use configurable values
4
+ * updated OPM_Alerts to use configurable values
5
+ * show_help fixed for some scripts
6
+ * show_help shows defaulted params and options
7
+ * added command line overrides of configuration values
8
+ * moved configuration into a module
9
+ * added basic configuration and tests.
10
+ * added tests for base class.
11
+ * added base class for all Geeklet scripts.
12
+ * added tests for the main geeklet engine
13
+ * added tests for Next_Months_Calendar script
14
+ * added tests for Trash_Usage script
15
+
16
+ === 0.0.6 2010-04-10
17
+
18
+ * updated the dependencies in the gemspec
19
+
1
20
  === 0.0.2 2010-02-07
2
21
 
3
22
  * Added weather script from Ted Wise.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
@@ -4,5 +4,5 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
4
4
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../vendor'
5
5
 
6
6
  require 'geeklets'
7
-
8
- Geeklets.run(ARGV)
7
+ g = Geeklets.new
8
+ g.run(ARGV)
@@ -1,9 +1,10 @@
1
- class Next_Months_Calendar
1
+ class Next_Months_Calendar < Geeklet
2
2
 
3
3
  def run(params)
4
+ super(:Next_Months_Calendar, params)
4
5
  today = Date.today
5
6
  nextmonth = today >> 1
6
- system("cal","#{nextmonth.month}","#{nextmonth.year}")
7
+ Kernel.system("cal","#{nextmonth.month}","#{nextmonth.year}")
7
8
  end
8
9
 
9
10
  end
@@ -3,33 +3,18 @@ require 'rubygems'
3
3
  require 'open-uri'
4
4
  require 'nokogiri'
5
5
 
6
- class OPM_Alerts
7
- URL = "http://www.opm.gov/status/index.aspx"
6
+ class OPM_Alerts < Geeklet
7
+ registerConfiguration :OPM_Alerts, :URL, :default => "http://www.opm.gov/status/index.aspx", :description => "OPM website URL", :type => :string
8
+ registerConfiguration :OPM_Alerts, :width, :default => 40, :description => "Word wrap width", :type => :int
8
9
 
9
- def die
10
- puts <<-EOS
11
- opm-status
12
-
13
- USAGE:
14
-
15
- \topm-status [wrapping-width]
16
-
17
- Returns U.S. Office of Personnel Management status Alerts.
18
-
19
- [wrapping-width] is an integer to limit the width of the descriptions
20
- Defaults to: 40
21
-
22
- EOS
23
-
24
- exit
10
+ def description
11
+ "Returns U.S. Office of Personnel Management status Alerts."
25
12
  end
26
13
 
27
14
  def run(params)
28
- die if params[0] == "-h"
29
-
30
- width = (params[1] and params[1].to_i) || 40
31
-
32
- doc = Nokogiri::HTML(open(URL))
15
+ super(:OPM_Alerts, params)
16
+
17
+ doc = Nokogiri::HTML(open(configurableValue(:OPM_Alerts, :URL)))
33
18
 
34
19
  date_str = doc.css('#_ctl0__ctl0_DisplayDateSpan').text.strip
35
20
  begin
@@ -52,6 +37,7 @@ EOS
52
37
  status = "Not found" if status.length == 0
53
38
 
54
39
  # display results
40
+ width = configurableValue(:OPM_Alerts, :width)
55
41
  puts Utility.wrap_text("#{date_str} - #{title}", width, date_str.length + 3, :outdent)
56
42
  puts "-" * width
57
43
  puts Utility.wrap_text(status, width)
@@ -1,7 +1,8 @@
1
- class Trash_Usage
1
+ class Trash_Usage < Geeklet
2
2
 
3
3
  def run(params)
4
- system("du -sh ~/.Trash/ | awk '{print \"Trash is using \"$1}'")
4
+ super(:Trash_Usage, params)
5
+ Kernel.system("du -sh ~/.Trash/ | awk '{print \"Trash is using \"$1}'")
5
6
  end
6
7
 
7
8
  end
@@ -3,40 +3,25 @@ require 'rubygems'
3
3
  require 'chronic'
4
4
  require 'mechanize'
5
5
 
6
- FEED_URL = "http://www.vre.org/service/daily-download.html"
7
- TRAIN_LINES = {"fbg_delay" => :fredericksburg, "mss_delay" => :manassas}
8
-
9
- class VRE_Alerts
10
-
11
- def die
12
- puts <<-EOS
13
- vre-alert
14
-
15
- USAGE:
16
-
17
- \tvre-alert [rail_lines] [wrapping-width] [specific-date]
18
-
19
- Returns Virgina Railway Express (VRE) Alerts.
20
-
21
- [rail_lines] specifies which rail lines you want alerts for.
22
- Can be:
23
- \tfredericsburg - for the Fredericsburg line
24
- \tmanassas - for the Manassas line
25
- \tboth - for both lines.
26
- Defaults to: both
6
+ class VRE_Alerts < Geeklet
7
+ registerConfiguration :VRE_Alerts, :URL, :default => "http://www.vre.org/service/daily-download.html", :description => "VRE website URL", :type => :string
8
+ registerConfiguration :VRE_Alerts, :lines, :default => "both", :description => "Which rail line. (manassas, fredericksburg, or both)", :type => :string
9
+ registerConfiguration :VRE_Alerts, :width, :default => 40, :description => "Wrapping width", :type => :int
10
+ registerConfiguration :VRE_Alerts, :date, :default => "today", :description => "A string parseable by Date::parse which is the date from the VRE daily download to display. NOTE: this does not access history, it only allows you to choose a specific entry from the Daily Download to render.", :type => :string
11
+
12
+ def name
13
+ "VRE_Alerts"
14
+ end
27
15
 
28
- [wrapping-width] is an integer to limit the width of the descriptions
29
- Defaults to: 40
16
+ def description
17
+ "Returns Virgina Railway Express (VRE) Alerts."
18
+ end
30
19
 
31
- [specific-date] is a string parseable by Date::parse which is the date from
32
- the VRE daily download to display. NOTE: this does not access history, it only
33
- allows you to choose a specific entry from the Daily Download to render. Mostly
34
- used for debugging.
35
- Defaults to: The current system Date.
36
-
37
- EOS
38
-
39
- exit
20
+ def line(cell_class)
21
+ case cell_class
22
+ when "fbg_delay" then :fredericksburg
23
+ when "mss_delay" then :manassas
24
+ end
40
25
  end
41
26
 
42
27
  # >> notice.search("tr")[2].search("td")[0].attributes["class"].value
@@ -68,7 +53,8 @@ class VRE_Alerts
68
53
  end
69
54
 
70
55
  cell_class = cells[0].attributes["class"].value unless cells[0].text.empty?
71
- detail[service] << {:line => TRAIN_LINES[cell_class], :train => cells[0].text, :description => cells[1].text} if @rail_lines == :both || @rail_lines == TRAIN_LINES[cell_class]
56
+ rail_lines = configurableValue(:VRE_Alerts, :lines).to_sym
57
+ detail[service] << {:line => line(cell_class), :train => cells[0].text, :description => cells[1].text} if rail_lines == :both || rail_lines == line(cell_class)
72
58
  else
73
59
  next
74
60
  end
@@ -100,23 +86,17 @@ class VRE_Alerts
100
86
  end
101
87
 
102
88
  def run(params)
103
- die if params[0] == "-h"
104
-
105
- @rail_lines = (params[0] || "both").to_sym
106
- width = (params[1] and params[1].to_i) || 40
107
- alert_date = (params[2] and Date.parse(params[2])) || Date.today
108
-
109
- #debug - set a date of interest, and rail line of interest
110
- # alert_date = Date.civil(2010, 1, 13)
111
- # @rail_lines = :fredericksburg
89
+ super(:VRE_Alerts, params)
112
90
 
113
91
  agent = Mechanize.new
114
- agent.get(FEED_URL)
92
+ agent.get(configurableValue(:VRE_Alerts, :URL))
115
93
  notices = agent.page.search(".format").map{ |notice| parse_notice(notice) }
116
94
 
117
95
  #debug
118
96
  #puts notices.to_yaml
119
97
 
98
+ width = configurableValue(:VRE_Alerts, :width)
99
+ alert_date = configurableValue(:VRE_Alerts, :date)
120
100
  render_notice(notices.select{ |notice| notice[:date] == alert_date }.shift, width)
121
101
  end
122
102
 
@@ -5,86 +5,65 @@ require 'open-uri'
5
5
  require 'chronic'
6
6
  require 'htmlentities'
7
7
 
8
- class WMATA_Alerts
8
+ class WMATA_Alerts < Geeklet
9
+ registerConfiguration :WMATA_Alerts, :URL, :default => "http://www.wmata.com/rider_tools/metro_service_status/feeds/rail.xml", :description => "WMATA website URL", :type => :string
10
+ registerConfiguration :WMATA_Alerts, :width, :default => 40, :description => "Wrapping width", :type => :int
11
+ registerConfiguration :WMATA_Alerts, :history, :default => "7 days ago", :description => "how many days of feed history to display. Can be anything parseable by Chronic gem.", :type => :string
9
12
 
10
- REPLACEMENTS =
11
- [
12
- ["p.m.", "pm"],
13
- ["a.m.", "am"]
14
- ]
15
-
16
- FEED_URL = "http://www.wmata.com/rider_tools/metro_service_status/feeds/rail.xml"
17
-
18
- def die
19
- puts <<-EOS
20
- metro-feed
21
-
22
- USAGE:
23
-
24
- \tmetro-feed [history] [wrapping-width]
25
-
26
- Returns WMATA feed information for metro lines.
27
-
28
- [history] is how many days of feed history to display.
29
- \tdefaults to 7 days. Can be anything parseable by Chronic gem
30
-
31
- [wrapping-width] is the limit to how wide the text can be
32
- \tdefaults to 40 characters. should be a positive integer value.
33
-
34
- Requires gems: chronic, htmlentities
35
-
36
-
37
- EOS
38
-
39
- exit
13
+ def name
14
+ "WMATA_Alerts"
40
15
  end
41
-
16
+
17
+ def description
18
+ "Returns WMATA feed information for metro lines."
19
+ end
20
+
21
+ def translate(message)
22
+ [
23
+ ["p.m.", "pm"],
24
+ ["a.m.", "am"]
25
+ ].each { |r| message.gsub!(r[0], r[1]) }
26
+ message
27
+ end
28
+
42
29
  def run(params)
30
+ super(:WMATA_Alerts, params)
43
31
 
44
- die if params[0] == "-h"
32
+ rss_content = ""
45
33
 
46
- @cutoff_string = params[0] || "7 days ago"
47
- @width = params[1] || "40"
48
- @width = @width.to_s.to_i
49
-
50
- @cutoff = Chronic.parse(@cutoff_string)
51
-
52
- @rss_content = ""
53
-
54
- open(FEED_URL) do |f|
55
- @rss_content = f.read
34
+ open(configurableValue(:WMATA_Alerts, :URL)) do |f|
35
+ rss_content = f.read
56
36
  end
57
37
 
58
- @rss = RSS::Parser.parse(@rss_content, false)
38
+ rss = RSS::Parser.parse(rss_content, false)
59
39
 
60
- @item_hash = {}
40
+ item_hash = {}
61
41
 
62
42
  # filter down to the items we want.
63
- @rss.items.each do |item|
64
- @item_hash[item.pubDate] = item unless item.pubDate < @cutoff
43
+ rss.items.each do |item|
44
+ item_hash[item.pubDate] = item unless item.pubDate < Chronic.parse(configurableValue(:WMATA_Alerts, :history))
65
45
  end
66
46
 
67
- if @item_hash.empty?
47
+ if item_hash.empty?
68
48
  puts "No data from WMATA feed."
69
49
  else
70
- @coder = HTMLEntities.new
71
- @item_hash.keys.sort.reverse.each do |key|
72
- item = @item_hash[key]
50
+ coder = HTMLEntities.new
51
+ item_hash.keys.sort.reverse.each do |key|
52
+ item = item_hash[key]
73
53
 
74
54
  title = "#{item.pubDate.strftime('%x')} - #{item.title}"
75
55
  puts title
76
56
  puts ("-" * title.length)
77
57
 
78
- message = @coder.decode(item.description)
79
- REPLACEMENTS.each do |r|
80
- message = message.gsub(r[0], r[1])
81
- end
58
+ message = coder.decode(item.description)
59
+ message = translate(message)
82
60
  subject, *body = message.split(".")
83
61
 
84
- puts Utility.wrap_text(subject+"...", @width)
62
+ width = configurableValue(:WMATA_Alerts, :width)
63
+ puts Utility.wrap_text(subject + "...", width)
85
64
  body.each do |sentence|
86
- puts Utility.wrap_text(sentence+".", @width, 3, :all)
87
- end
65
+ puts Utility.wrap_text(sentence + ".", width, 3, :all)
66
+ end
88
67
 
89
68
  puts
90
69
  end
@@ -0,0 +1,68 @@
1
+ require 'unregistered_config_value_error'
2
+ require 'configuration_required_error'
3
+ require 'trollop'
4
+ require 'yaml'
5
+
6
+ module Configurable
7
+
8
+ # configurations should be a hash of hashes, where the first key is the calculator type, and the second key is the tag
9
+ def configurations
10
+ @@configuration ||= {}
11
+ end
12
+
13
+ def isHelp?(param)
14
+ param.to_s.downcase == 'help'
15
+ end
16
+
17
+ def configurableValue(group, key)
18
+ raise UnregisteredConfigValueError unless configurations.include?(group)
19
+ raise UnregisteredConfigValueError unless configurations[group].include?(key)
20
+ value = configurations[group][key][:override] || configurations[group][key][:stored] || configurations[group][key][:default]
21
+ raise ConfigurationRequiredError unless value
22
+ value
23
+ end
24
+
25
+ def registerConfiguration(group, key, options = {})
26
+ configurations[group] ||= {}
27
+ configurations[group][key] = options
28
+ end
29
+
30
+ def command_parser(group)
31
+ groupConfigs = configurations[group]
32
+ return unless groupConfigs #if there are no configs defined, there is nothing to do.
33
+
34
+ parser = Trollop::Parser.new do
35
+ groupConfigs.each do |key, options|
36
+ # our concept of a default is different from trollop's, so remove any default key and value
37
+ defaultValue = options[:stored] || options[:default]
38
+ if defaultValue
39
+ opt key, options[:description], options.merge({ :default => defaultValue })
40
+ else
41
+ opt key, options[:description], options
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def add_overrides(group, params)
48
+ return if (params.nil? || params.empty?) # nothing to do in this case
49
+ raise Trollop::HelpNeeded if isHelp?(params[0])
50
+
51
+ groupConfigs = configurations[group]
52
+ trollop_opts = command_parser(group).parse(params)
53
+ trollop_opts.each do |key, value|
54
+ groupConfigs[key][:override] = value if groupConfigs.key?(key)
55
+ end
56
+
57
+ # puts "trollop opts:"
58
+ # puts trollop_opts.to_yaml
59
+ # puts
60
+ # puts "group configs:"
61
+ # puts groupConfigs.to_yaml
62
+ end
63
+
64
+ def self.included(base)
65
+ base.extend(Configurable)
66
+ end
67
+
68
+ end
@@ -0,0 +1,3 @@
1
+ class ConfigurationRequiredError < Exception
2
+
3
+ end
@@ -0,0 +1,39 @@
1
+ require 'configurable'
2
+
3
+ class Geeklet
4
+ include Configurable
5
+
6
+
7
+ def name
8
+ self.class.to_s
9
+ end
10
+
11
+ def description
12
+ "No description specified for this geeklet."
13
+ end
14
+
15
+ def show_help(group)
16
+ parser = command_parser(group)
17
+ Kernel.puts(
18
+ <<-EOS
19
+ Geeklet: #{name}
20
+
21
+ Description: #{description}
22
+
23
+ EOS
24
+ )
25
+ parser.educate
26
+ end
27
+
28
+ def run(group, params)
29
+ begin
30
+ add_overrides(group, params)
31
+ rescue => e
32
+ show_help(group)
33
+ # Kernel.puts e.inspect
34
+ Kernel.exit
35
+ end
36
+ true
37
+ end
38
+
39
+ end
@@ -1,51 +1,61 @@
1
1
  $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  require 'pathname'
5
5
  require 'utility'
6
- require 'trollop'
6
+ require 'geeklet'
7
+ require 'yaml'
7
8
 
8
9
  class Geeklets
9
10
 
10
- def self.show_usage
11
- puts "Usage: geeklets <geeklet-script> [relevant-parameters-for-script]"
12
- puts
11
+ def initialize(scripts = {})
12
+ @geeklet_scripts = scripts
13
+ if @geeklet_scripts.empty?
14
+ cwd = File.dirname(__FILE__)
15
+ children = Pathname.new(cwd).children
16
+ children.reject! { |child| !child.directory? }
17
+ children.each do |child_dir|
18
+ geeklet_name = child_dir.basename.to_s
19
+ geeklet_file = geeklet_name.downcase
20
+ begin
21
+ Kernel.require "#{geeklet_name}/#{geeklet_file}"
22
+ @geeklet_scripts[geeklet_name] = Kernel.eval("#{geeklet_name}.new")
23
+ rescue => e
24
+ Kernel.puts "Problem loading #{geeklet_name} geeklet."
25
+ # Kernel.puts e.inspect
26
+ # Kernel.puts e.backtrace
27
+ next
28
+ end
29
+ end
30
+ end
13
31
  end
14
32
 
15
- def self.show_known_scripts
16
- puts "These are the currently known geeklet scripts:"
17
- puts
18
- script_inventory.each { |script| puts "\t#{script}"}
33
+ def show_usage
34
+ puts "Usage: geeklets <geeklet-script> [relevant-parameters-for-script]"
19
35
  puts
20
36
  end
21
-
22
- def self.script_inventory
23
- cwd = File.dirname(__FILE__)
24
- children = Pathname.new(cwd).children
25
- children.reject! { |child| !child.directory? }
26
- children.map! { |child| child.basename.to_s }
27
- end
28
-
29
- def self.run_geeklet(geeklet, params)
30
- require "#{geeklet}/#{geeklet.downcase}"
31
- obj = eval("#{geeklet}.new")
32
- obj.run(params)
37
+
38
+ def show_known_scripts
39
+ Kernel.puts "These are the currently known geeklet scripts:"
40
+ Kernel.puts
41
+ Kernel.puts "There are no defined geeklet scripts." if @geeklet_scripts.empty?
42
+ @geeklet_scripts.keys.sort.each { |key| Kernel.puts "\t#{key}" }
43
+ Kernel.puts
33
44
  end
34
45
 
35
- def self.run(params)
36
- if params.empty?
46
+ def run(params)
47
+ if params.nil? || params.empty?
37
48
  show_usage
38
49
  show_known_scripts
39
50
  else
40
51
  geeklet = params.shift
41
- if script_inventory.include?(geeklet)
42
- run_geeklet(geeklet, params)
52
+ if @geeklet_scripts.include?(geeklet)
53
+ @geeklet_scripts[geeklet].run(params)
43
54
  else
44
- puts "I do not know how to run the #{geeklet} geeklet."
55
+ Kernel.puts "I do not know how to run the #{geeklet} geeklet."
45
56
  show_known_scripts
46
57
  end
47
58
  end
48
-
49
59
  end
50
60
 
51
- end
61
+ end
@@ -0,0 +1,3 @@
1
+ class UnregisteredConfigValueError < Exception
2
+
3
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'Next_Months_Calendar/next_months_calendar'
3
+
4
+ describe Next_Months_Calendar do
5
+
6
+ before { @script = Next_Months_Calendar.new }
7
+
8
+ subject { @script }
9
+
10
+ describe "In general" do
11
+ it { should be_a_kind_of(Geeklet)}
12
+ end
13
+
14
+ describe :run do
15
+
16
+ context "when this month is April" do
17
+ it "should get the calendar for next month" do
18
+ Date.should_receive(:today).and_return(Date.civil(2010, 4, 26))
19
+ Kernel.should_receive(:system).with("cal","5","2010")
20
+ @script.run([])
21
+ end
22
+ end
23
+
24
+ context "when this month is December" do
25
+ it "should get the calendar for next month, in the next year" do
26
+ Date.should_receive(:today).and_return(Date.civil(2010, 12, 25))
27
+ Kernel.should_receive(:system).with("cal","1","2011")
28
+ @script.run([])
29
+ end
30
+ end
31
+
32
+ context "when the following month has fewer days" do
33
+ it "should get the calendar for next month, in the next year" do
34
+ Date.should_receive(:today).and_return(Date.civil(2010, 1, 31))
35
+ Kernel.should_receive(:system).with("cal","2","2010")
36
+ @script.run([])
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'Trash_Usage/trash_usage'
3
+
4
+ describe Trash_Usage do
5
+
6
+ before { @script = Trash_Usage.new }
7
+
8
+ subject { @script }
9
+
10
+ describe "in general" do
11
+ it { should be_a_kind_of(Geeklet) }
12
+ end
13
+
14
+ describe :run do
15
+
16
+ it "should get the trash usage" do
17
+
18
+ Kernel.should_receive(:system).with("du -sh ~/.Trash/ | awk '{print \"Trash is using \"$1}'")
19
+
20
+ @script.run([])
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,72 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'configurable'
3
+
4
+ describe Configurable do
5
+
6
+ before do
7
+ klass = Class.new do
8
+ include Configurable
9
+ end
10
+ @configurable = klass.new
11
+ end
12
+
13
+ describe :configurableValue do
14
+
15
+ context "when group not registered" do
16
+ it "should throw an exception" do
17
+ lambda { @configurable.configurableValue("no_group", "someUnregisteredKey") }.should raise_exception(UnregisteredConfigValueError)
18
+ end
19
+ end
20
+
21
+ context "when group is registered but configurable value not registered" do
22
+ it "should throw an exception" do
23
+ @configurable.registerConfiguration("group", "someRegisteredKey")
24
+ lambda { @configurable.configurableValue("group", "someUnregisteredKey") }.should raise_exception(UnregisteredConfigValueError)
25
+ end
26
+ end
27
+
28
+ context "when configurable value is registered" do
29
+
30
+ context "with a default value" do
31
+ it "should return the default value" do
32
+ @configurable.registerConfiguration("group", "someRegisteredKey", :default => "some Default Value")
33
+ @configurable.configurableValue("group", "someRegisteredKey").should == "some Default Value"
34
+ end
35
+ end
36
+
37
+ context "without a default value" do
38
+ it "should indicate that configuration is necessary" do
39
+ @configurable.registerConfiguration("group", "someRegisteredKey")
40
+ lambda { @configurable.configurableValue("group", "someRegisteredKey") }.should raise_exception(ConfigurationRequiredError)
41
+ end
42
+ end
43
+
44
+ context "when value is overridden" do
45
+ it "should return the overridden value" do
46
+ @configurable.registerConfiguration("group", "someRegisteredKey", :default => "default", :type => :string)
47
+ @configurable.add_overrides("group", ["-s", "override"])
48
+ @configurable.configurableValue("group", "someRegisteredKey").should == "override"
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+
55
+
56
+ end
57
+
58
+ describe :isHelp do
59
+
60
+ it "should return true when param is 'help'" do
61
+ help = ['Help', 'help', "HeLp"]
62
+ help.each { |param| @configurable.isHelp?(param).should be_true }
63
+ end
64
+
65
+ it "should be false when the param is not 'help'" do
66
+ not_help = [2, nil, ""]
67
+ not_help.each { |param| @configurable.isHelp?(param).should be_false }
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'geeklet'
3
+
4
+ describe Geeklet do
5
+
6
+ before { @geeklet = Geeklet.new }
7
+
8
+ subject { @geeklet }
9
+
10
+ it { should respond_to :run }
11
+
12
+ describe :run do
13
+
14
+ context "When params is nil" do
15
+ subject { @geeklet.run("group", nil)}
16
+ it { should be_true }
17
+ end
18
+
19
+ context "When params is empty" do
20
+ subject { @geeklet.run("group", [])}
21
+ it { should be_true }
22
+ end
23
+
24
+ context "When params has items" do
25
+ subject { @geeklet.run("group", ["one", 2, "three"])}
26
+ it { should be_true }
27
+ end
28
+
29
+ context "When params has 'help' as first item" do
30
+ it "should show help and exit" do
31
+ @geeklet.should_receive(:show_help)
32
+ Kernel.should_receive(:exit)
33
+
34
+ @geeklet.run("group", ["Help", 2, "4.5"])
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+
41
+
42
+ describe :show_help do
43
+
44
+ it "should display usage information" do
45
+ parser = mock("command_parser")
46
+ @geeklet.should_receive(:command_parser).with("group").and_return(parser)
47
+ @geeklet.should_receive(:name).and_return("Script Name")
48
+ @geeklet.should_receive(:description).and_return("Some script description")
49
+ Kernel.should_receive(:puts).with(
50
+ <<-EOS
51
+ Geeklet: Script Name
52
+
53
+ Description: Some script description
54
+
55
+ EOS
56
+ )
57
+ parser.should_receive(:educate)
58
+
59
+ @geeklet.show_help("group")
60
+ end
61
+
62
+ end
63
+
64
+
65
+ end
@@ -1,15 +1,200 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'geeklets'
2
3
 
3
- describe "Geeklets" do
4
+ module GeekletExampleHelperMethods
5
+ def mock_no_scripts
6
+ mock_cwd = mock("cwd")
7
+ mock_cwd_pathname = mock("cwd Pathname")
8
+ mock_children = []
4
9
 
5
- it "should know how to show usage"
10
+ File.should_receive(:dirname).with(any_args()).and_return(mock_cwd)
11
+ Pathname.should_receive(:new).with(mock_cwd).and_return(mock_cwd_pathname)
12
+ mock_cwd_pathname.should_receive(:children).and_return(mock_children)
13
+ mock_children.should_receive(:reject!)
14
+
6
15
 
7
- it "should know how to show the valid scripts"
16
+ geeklets = Geeklets.new
17
+ end
18
+
19
+ def mock_some_scripts_no_problems
20
+ mock_cwd = mock("cwd")
21
+ mock_cwd_pathname = mock("cwd Pathname")
22
+ mock_children = [ mock("Dir1"), mock("Dir2"), mock("Dir3")]
23
+ mock_children_basenames = ["Dir1.Basename", "Dir2.Basename", "Dir3.Basename"]
24
+ mock_script_1 = mock("script1")
25
+ mock_script_2 = mock("script2")
26
+ mock_script_3 = mock("script3")
27
+
28
+ File.should_receive(:dirname).with(any_args()).and_return(mock_cwd)
29
+ Pathname.should_receive(:new).with(mock_cwd).and_return(mock_cwd_pathname)
30
+ mock_cwd_pathname.should_receive(:children).and_return(mock_children)
31
+ mock_children[0].should_receive(:directory?).and_return(true)
32
+ mock_children[1].should_receive(:directory?).and_return(true)
33
+ mock_children[2].should_receive(:directory?).and_return(true)
34
+
35
+ mock_children[0].should_receive(:basename).and_return(mock_children_basenames[0])
36
+ Kernel.should_receive(:require).with("Dir1.Basename/dir1.basename")
37
+ Kernel.should_receive(:eval).with("Dir1.Basename.new").and_return(mock_script_1)
38
+
39
+ mock_children[1].should_receive(:basename).and_return(mock_children_basenames[1])
40
+ Kernel.should_receive(:require).with("Dir2.Basename/dir2.basename")
41
+ Kernel.should_receive(:eval).with("Dir2.Basename.new").and_return(mock_script_2)
42
+
43
+ mock_children[2].should_receive(:basename).and_return(mock_children_basenames[2])
44
+ Kernel.should_receive(:require).with("Dir3.Basename/dir3.basename")
45
+ Kernel.should_receive(:eval).with("Dir3.Basename.new").and_return(mock_script_3)
46
+
47
+ geeklets = Geeklets.new
48
+ end
49
+
50
+ def mock_some_scripts_with_problems
51
+ mock_cwd = mock("cwd")
52
+ mock_cwd_pathname = mock("cwd Pathname")
53
+ mock_children = [ mock("Dir1"), mock("Dir2"), mock("Dir3")]
54
+ mock_children_basenames = ["Dir1.Basename", "Dir2.Basename", "Dir3.Basename"]
55
+ mock_script_3 = mock("script3")
56
+
57
+ File.should_receive(:dirname).with(any_args()).and_return(mock_cwd)
58
+ Pathname.should_receive(:new).with(mock_cwd).and_return(mock_cwd_pathname)
59
+ mock_cwd_pathname.should_receive(:children).and_return(mock_children)
60
+ mock_children[0].should_receive(:directory?).and_return(true)
61
+ mock_children[1].should_receive(:directory?).and_return(true)
62
+ mock_children[2].should_receive(:directory?).and_return(true)
63
+
64
+ mock_children[0].should_receive(:basename).and_return(mock_children_basenames[0])
65
+ Kernel.should_receive(:require).with("Dir1.Basename/dir1.basename").and_raise("can't require")
66
+
67
+ mock_children[1].should_receive(:basename).and_return(mock_children_basenames[1])
68
+ Kernel.should_receive(:require).with("Dir2.Basename/dir2.basename")
69
+ Kernel.should_receive(:eval).with("Dir2.Basename.new").and_raise("can't create")
70
+ Kernel.should_receive(:puts).with("Problem loading Dir1.Basename geeklet.").ordered
71
+
72
+ mock_children[2].should_receive(:basename).and_return(mock_children_basenames[2])
73
+ Kernel.should_receive(:require).with("Dir3.Basename/dir3.basename")
74
+ Kernel.should_receive(:eval).with("Dir3.Basename.new").and_return(mock_script_3)
75
+ Kernel.should_receive(:puts).with("Problem loading Dir2.Basename geeklet.").ordered
76
+
77
+ geeklets = Geeklets.new
78
+ end
79
+
80
+ end
81
+
82
+ describe Geeklets do
83
+
84
+ before(:all) { @geeklets = Geeklets.new }
85
+
86
+ subject { @geeklets }
87
+
88
+ it { should respond_to :show_usage }
89
+ it { should respond_to :show_known_scripts }
90
+ it { should respond_to :run }
91
+ end
92
+
93
+ describe Geeklets do
94
+
95
+ context :initialize, "when there are no scripts" do
96
+ include GeekletExampleHelperMethods
8
97
 
9
- it "should know how to obtain the list of valid scripts"
98
+ before(:each) { @geeklets = mock_no_scripts }
10
99
 
11
- it "should know how to run an individual script"
100
+ it "should produce an empty list" do
101
+ Kernel.should_receive(:puts).with("These are the currently known geeklet scripts:").ordered
102
+ Kernel.should_receive(:puts).with(no_args()).ordered
103
+ Kernel.should_receive(:puts).with("There are no defined geeklet scripts.").ordered
104
+ Kernel.should_receive(:puts).with(no_args()).ordered
105
+
106
+ @geeklets.show_known_scripts
107
+ end
108
+ end
12
109
 
13
- it "should know how to parse the parameters to determine what script to run"
110
+ context :initialize, "when there are scripts with no problems" do
111
+ include GeekletExampleHelperMethods
112
+
113
+ before(:each) { @geeklets = mock_some_scripts_no_problems }
114
+
115
+ it "should not produce an empty list" do
116
+ Kernel.should_receive(:puts).with("These are the currently known geeklet scripts:").ordered
117
+ Kernel.should_receive(:puts).with(no_args()).ordered
118
+ Kernel.should_receive(:puts).with("\tDir1.Basename").ordered
119
+ Kernel.should_receive(:puts).with("\tDir2.Basename").ordered
120
+ Kernel.should_receive(:puts).with("\tDir3.Basename").ordered
121
+ Kernel.should_receive(:puts).with(no_args()).ordered
122
+
123
+ @geeklets.show_known_scripts
124
+ end
125
+ end
14
126
 
127
+ context :initialize, "when there are scripts with problems" do
128
+ include GeekletExampleHelperMethods
129
+
130
+ before(:each) { @geeklets = mock_some_scripts_with_problems }
131
+
132
+ it "should skip the scripts with problems and report them" do
133
+ Kernel.should_receive(:puts).with("These are the currently known geeklet scripts:").ordered
134
+ Kernel.should_receive(:puts).with(no_args()).ordered
135
+ Kernel.should_receive(:puts).with("\tDir3.Basename").ordered
136
+ Kernel.should_receive(:puts).with(no_args()).ordered
137
+
138
+ @geeklets.show_known_scripts
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ describe Geeklets do
145
+
146
+ before { @geeklets = Geeklets.new }
147
+
148
+ subject { @geeklets.run }
149
+
150
+ context "when given no parameters" do
151
+
152
+ it "should show usage and available scripts" do
153
+ @geeklets.should_receive(:show_usage)
154
+ @geeklets.should_receive(:show_known_scripts)
155
+
156
+ @geeklets.run(nil)
157
+ end
158
+
159
+ end
160
+
161
+ context "when given empty parameters" do
162
+
163
+ it "should show usage and available scripts" do
164
+ @geeklets.should_receive(:show_usage)
165
+ @geeklets.should_receive(:show_known_scripts)
166
+
167
+ @geeklets.run([])
168
+ end
169
+
170
+ end
171
+
172
+ context "when given parmeters for a non existant script" do
173
+
174
+ it "should indicate that it doesn't understand, and show the available scripts" do
175
+ Kernel.should_receive(:puts).with("I do not know how to run the noscript geeklet.").ordered
176
+ @geeklets.should_receive(:show_known_scripts)
177
+
178
+ @geeklets.run(["noscript"])
179
+ end
180
+
181
+ end
182
+
183
+ context "when given parmeters for an existing script" do
184
+
185
+ before do
186
+ @script_hash = mock("script hash")
187
+ @script_hash.should_receive(:empty?).and_return(false)
188
+ @geeklets = Geeklets.new(@script_hash)
189
+ end
190
+
191
+ it "should attempt to run that script" do
192
+ @script_hash.should_receive(:include?).with("some_script").and_return(true)
193
+ @script_hash.should_receive(:[]).with("some_script").and_return(mock_script = mock("some_script"))
194
+ mock_script.should_receive(:run).with(["some_params"])
195
+
196
+ @geeklets.run(["some_script", "some_params"])
197
+ end
198
+
199
+ end
15
200
  end
@@ -2,7 +2,6 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
 
4
4
  require 'rubygems'
5
- require 'geeklets'
6
5
  require 'spec'
7
6
  require 'spec/autorun'
8
7
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 6
9
- version: 0.0.6
8
+ - 7
9
+ version: 0.0.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - John F. Schank III
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-10 00:00:00 -04:00
17
+ date: 2010-05-02 00:00:00 -04:00
18
18
  default_executable: geeklets
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -124,8 +124,16 @@ files:
124
124
  - lib/VRE_Alerts/vre_alerts.rb
125
125
  - lib/WMATA_Alerts/wmata_alerts.rb
126
126
  - lib/Weather/weather.rb
127
+ - lib/configurable.rb
128
+ - lib/configuration_required_error.rb
129
+ - lib/geeklet.rb
127
130
  - lib/geeklets.rb
131
+ - lib/unregistered_config_value_error.rb
128
132
  - lib/utility.rb
133
+ - spec/Next_Months_Calendar/next_months_calendar_spec.rb
134
+ - spec/Trash_Usage/trash_usage_spec.rb
135
+ - spec/configurable_spec.rb
136
+ - spec/geeklet_spec.rb
129
137
  - spec/geeklets_spec.rb
130
138
  - spec/spec.opts
131
139
  - spec/spec_helper.rb
@@ -162,6 +170,10 @@ signing_key:
162
170
  specification_version: 3
163
171
  summary: Scripts for GeekTool
164
172
  test_files:
173
+ - spec/configurable_spec.rb
174
+ - spec/geeklet_spec.rb
165
175
  - spec/geeklets_spec.rb
176
+ - spec/Next_Months_Calendar/next_months_calendar_spec.rb
166
177
  - spec/spec_helper.rb
178
+ - spec/Trash_Usage/trash_usage_spec.rb
167
179
  - spec/utility_spec.rb