geeklets 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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