coderifous-tornado 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,93 @@
1
+ Tornado
2
+ =======
3
+
4
+ Tornado is a ruby gem that let's you write ruby scripts that looks like this:
5
+
6
+ tell OSX do
7
+ hide_everything
8
+ end
9
+
10
+ tell Terminal do
11
+ open_new_tab("~/dev/web_site")
12
+
13
+ open_new_tab(DEV_DIR) do
14
+ tail "~/dev/web_site/log/*.log"
15
+ end
16
+
17
+ open_new_tab("~/dev/web_site") do
18
+ run "autotest"
19
+ end
20
+ end
21
+
22
+ tell Textmate do
23
+ minimize_all_windows
24
+ open DEV_DIR
25
+ resize 400, "100%"
26
+ reposition :east
27
+ end
28
+
29
+ tell Firefox do
30
+ open_new_tab("http://web-site.local")
31
+ end
32
+
33
+ Documentation
34
+ -------------
35
+
36
+ None yet - this thing is new.
37
+
38
+ Why
39
+ -----
40
+
41
+ Tornado sits on top of Appscript, which is an Apple event bridge.
42
+ Appscript is GREAT, I wanted something even higher level. Something
43
+ that would just let me easily do the common things I want to do when
44
+ switching between projects: open terminals, run commands, open the
45
+ project in my text editor, minimize/hide other apps, etc.
46
+
47
+ See below for code comparisons:
48
+
49
+ Using Appscript directly:
50
+ -------------------------
51
+
52
+ # hide all apps
53
+
54
+ se = Appscript.app("System Events")
55
+ se.keystroke("h", :using => [ :command_down, :option_down ])
56
+
57
+ # open a tab in Terminal and run "autotest"
58
+
59
+ t = Appscript.app("Terminal")
60
+ t.launch unless t.is_running?
61
+ se.application_processes["Terminal"].keystroke("t", :using => :command_down)
62
+ tab = current_window.tabs.last
63
+ term.do_script("cd ~/dev/web_site && clear && autotest", :in => tab)
64
+
65
+ Using Tornado:
66
+ --------------
67
+
68
+ # hide all apps
69
+
70
+ tell OSX do
71
+ hide_everything
72
+ end
73
+
74
+ # open a tab in Terminal and run "autotest"
75
+ tell Terminal do
76
+ open_new_tab("~/dev/web_site") do
77
+ run "autotest"
78
+ end
79
+ end
80
+
81
+
82
+ Copyright and License
83
+ ---------------------
84
+
85
+ The MIT License
86
+
87
+ Copyright© 2008 Jim Garvin
88
+
89
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
92
+
93
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ %w[rubygems rake rake/clean fileutils].each { |f| require f }
2
+ $: << "lib"
3
+ require File.dirname(__FILE__) + '/lib/tornado'
4
+ require 'echoe'
5
+ require 'rake/testtask'
6
+ require 'rcov/rcovtask'
7
+
8
+ Echoe.new('tornado', Tornado::VERSION) do |p|
9
+ p.description = "Ruby DSL for easily launching, arranging and doing other simple tasks with Mac OS X applications."
10
+ p.url = "http://github.com/coderifous/tornado"
11
+ p.author = "Jim Garvin"
12
+ p.email = "jim at thegarvin dot com"
13
+ p.ignore_pattern = ["rdoc/*", "rcov/*"]
14
+ p.development_dependencies = []
15
+ p.runtime_dependencies = ['rb-appscript >=0.5.1']
16
+ end
17
+
18
+ Rcov::RcovTask.new do |t|
19
+ t.libs << "test" << "test/helpers"
20
+ t.pattern = 'test/test_*.rb'
21
+ t.output_dir = 'rcov'
22
+ t.verbose = true
23
+ end
24
+
25
+ Rake::TestTask.new do |t|
26
+ t.libs << "test" << "test/helpers"
27
+ t.test_files = FileList['test/test_*.rb']
28
+ t.verbose = true
29
+ end
30
+
@@ -0,0 +1,35 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'tornado'
5
+
6
+ DEV_DIR = "~/dev/cubenot_site"
7
+
8
+ tell OSX do
9
+ hide_everything
10
+ end
11
+
12
+ tell Terminal do
13
+ open_new_tab(DEV_DIR)
14
+
15
+ open_new_tab(DEV_DIR) do
16
+ tail "~/dev/cubenot_site/log/*.log"
17
+ end
18
+
19
+ open_new_tab(DEV_DIR) do
20
+ run "autotest"
21
+ end
22
+ end
23
+
24
+ tell Textmate do
25
+ minimize_all_windows
26
+ open DEV_DIR
27
+ resize 400, "100%", :animate => true
28
+ reposition :south_east, :animate => true
29
+ end
30
+
31
+ tell Firefox do
32
+ open_new_tab("http://cubenot-site.local")
33
+ end
34
+
35
+ Textmate.activate
@@ -0,0 +1,8 @@
1
+ module Tornado::Applications::Finder
2
+
3
+ def minimize_all_windows
4
+ app.activate
5
+ app.windows.collapsed.set(true) # finder uses "collapsed"
6
+ end
7
+
8
+ end
@@ -0,0 +1,9 @@
1
+ module Tornado::Applications::Firefox
2
+
3
+ # depends on Firefox being the default browser, and
4
+ # configured to open new pages in new tabs
5
+ def open_new_tab(*args)
6
+ OSX.open_location(*args)
7
+ end
8
+
9
+ end
@@ -0,0 +1,6 @@
1
+ module Tornado::Applications::Safari
2
+
3
+ def open_new_tab(*args)
4
+ end
5
+
6
+ end
@@ -0,0 +1,67 @@
1
+ module Tornado::Applications::Terminal
2
+
3
+ def open_new_tab(path=nil, &block)
4
+ Terminal.ensure_launched
5
+ Terminal.keystroke("t", :using => :command_down)
6
+ tab = Tab.new(app.windows.first.tabs.last)
7
+ if path
8
+ tab.cd(path)
9
+ tab.clear
10
+ end
11
+ if block_given?
12
+ tab.instance_eval(&block)
13
+ end
14
+ tab
15
+ end
16
+
17
+ # For some reason (a bug), we have to add the window's height to both y-values in the coordinates
18
+ def position_top_left_corner_at(x,y, animate=false)
19
+ b = current_bounds
20
+ app.windows[0].bounds.set([x, y + height, x + width, y + height + height])
21
+ end
22
+
23
+ # same bug is addressed here
24
+ def resize(w, h, animate=false)
25
+ b = current_bounds
26
+ w = absolutize_size(w, :width)
27
+ h = absolutize_size(h, :height)
28
+ app.windows[0].bounds.set([ b[0], b[1] + height, b[0] + w, b[1] + h + height ])
29
+ end
30
+
31
+ def absolutize_size(size, width_or_height)
32
+ if size.to_s[-1].chr == "%"
33
+ OSX.send("desktop_#{width_or_height}") * (size.to_f / 100)
34
+ else
35
+ size + height
36
+ end
37
+ end
38
+
39
+ class Tab
40
+ attr_reader :tab
41
+
42
+ def initialize(tab)
43
+ @tab = tab
44
+ end
45
+
46
+ def run(cmd)
47
+ Terminal.do_script(cmd, :in => @tab)
48
+ end
49
+
50
+ def tail(path)
51
+ run "tail -f #{path}"
52
+ end
53
+
54
+ def clear
55
+ run "clear"
56
+ end
57
+
58
+ def clear_scrollback
59
+ @tab.selected.set(true)
60
+ Terminal.keystroke("k", :using => :command_down)
61
+ end
62
+
63
+ def cd(path)
64
+ run "cd #{path}"
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,11 @@
1
+ module Tornado::Applications::Textmate
2
+ def open(*args)
3
+ args.each do |file_path|
4
+ file_path.sub!(/~/, ENV["HOME"])
5
+ app.open(file_path)
6
+ end
7
+ end
8
+ end
9
+
10
+ # in case I jack up textmate's drawer again:
11
+ # defaults write com.macromates.textmate OakProjectDrawerWidth 100
@@ -0,0 +1,160 @@
1
+ require 'osx'
2
+
3
+ module GenericActions
4
+ def close_all_windows
5
+ app.windows.close
6
+ end
7
+
8
+ def minimize_all_windows
9
+ app.activate
10
+ app.windows.get.select { |w| w.visible.get }.each do |window|
11
+ window.miniaturized.set(true)
12
+ end
13
+ end
14
+
15
+ def wait_for_me!
16
+ sleep(0.1) while !is_running?
17
+ end
18
+
19
+ def ensure_launched
20
+ unless is_running?
21
+ app.launch
22
+ wait_for_me!
23
+ end
24
+ end
25
+
26
+ def keystroke(*args)
27
+ OSX[name].keystroke(*args)
28
+ end
29
+
30
+ # blindly pass on unrecognized methods to the appscript proxy
31
+ def method_missing(meth, *args)
32
+ app.send(meth, *args)
33
+ end
34
+ end
35
+
36
+ module WindowPositionAndResizeActions
37
+ def current_bounds
38
+ app.windows[0].bounds.get
39
+ end
40
+
41
+ def position(cardinal_point, opts={})
42
+ x, y = nil, nil
43
+ case cardinal_point
44
+ when :north_east
45
+ x = OSX.desktop_width - width
46
+ y = 0
47
+ when :south_east
48
+ x = OSX.desktop_width - width
49
+ y = OSX.desktop_height - height
50
+ when :north_west
51
+ x, y = 0, 0
52
+ when :south_west
53
+ x = 0
54
+ y = OSX.desktop_height - height
55
+ end
56
+ position_top_left_corner_at(x, y, opts)
57
+ end
58
+
59
+ def position_top_left_corner_at(x, y, opts={})
60
+ b = current_bounds
61
+ end_bounds = [x, y, x + width, y + height]
62
+ if opts[:animate]
63
+ transition_to_bounds(b, end_bounds)
64
+ else
65
+ app.windows[0].bounds.set(end_bounds)
66
+ end
67
+ end
68
+
69
+ def width
70
+ b = current_bounds
71
+ b[2] - b[0]
72
+ end
73
+
74
+ def height
75
+ b = current_bounds
76
+ b[3] - b[1]
77
+ end
78
+
79
+ def resize(w, h, opts={})
80
+ b = current_bounds
81
+ w = absolutize_size(w, :width)
82
+ h = absolutize_size(h, :height)
83
+ end_bounds = [ b[0], b[1], b[0] + w, b[1] + h ]
84
+ if opts[:animate]
85
+ transition_to_bounds(b, end_bounds)
86
+ else
87
+ app.windows[0].bounds.set(end_bounds)
88
+ end
89
+ end
90
+
91
+ def transition_to_bounds(start_bounds, end_bounds)
92
+ # puts "From #{start_bounds.inspect} to #{end_bounds.inspect}"
93
+ steps = 50
94
+ factor = 100 / steps
95
+ 1.upto(steps) do |step|
96
+ frac = step.to_f * factor / 100
97
+ step_bounds = []
98
+ 0.upto(3) do |x|
99
+ step_bounds[x] = start_bounds[x] + ((end_bounds[x] - start_bounds[x]) * frac)
100
+ end
101
+ # puts "bounds: #{step_bounds.inspect}"
102
+ app.windows[0].bounds.set(step_bounds)
103
+ end
104
+ end
105
+
106
+ def absolutize_size(size, width_or_height)
107
+ if size.to_s[-1].chr == "%"
108
+ OSX.send("desktop_#{width_or_height}") * (size.to_f / 100)
109
+ else
110
+ size
111
+ end
112
+ end
113
+ end
114
+
115
+ module ExtensionHelpers
116
+ def extension
117
+ Tornado::Applications.const_get(name)
118
+ end
119
+
120
+ def extension_path
121
+ "applications/#{name.downcase.tr(" ", '_')}.rb"
122
+ end
123
+
124
+ def load_extension!
125
+ begin
126
+ require extension_path
127
+ self.extend(extension)
128
+ rescue NameError => e
129
+ STDERR.puts "Extension not loaded: Expected #{extension_path} to define module Tornado::Applications::#{name}"
130
+ STDERR.puts caller
131
+ rescue LoadError => e
132
+ STDERR.puts "Extension not found: #{extension_path}"
133
+ end
134
+ end
135
+ end
136
+
137
+ class GenericApplication
138
+ include GenericActions
139
+ include ExtensionHelpers
140
+ include WindowPositionAndResizeActions
141
+
142
+ attr_accessor :app, :name
143
+
144
+ def initialize(opts)
145
+ opts.each_pair { |k,v| self.send("#{k}=", v) }
146
+ self.app = Appscript.app(name)
147
+ end
148
+
149
+ def self.find_by_string(name)
150
+ if Appscript.app(name)
151
+ application = GenericApplication.new(:name => name)
152
+ application.load_extension!
153
+ Kernel.const_set(name, application)
154
+ return application
155
+ else
156
+ STDERR.puts "Couldn't find application named: #{name}"
157
+ return false
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,35 @@
1
+ class OSX
2
+ class << self
3
+ def hide_everything
4
+ system_events.keystroke("h", :using => [ :command_down, :option_down ])
5
+ end
6
+
7
+ def open_location(*args)
8
+ args.each { |url| system_events.open_location(url) }
9
+ end
10
+
11
+ def system_events
12
+ @system_events ||= Appscript.app("System Events")
13
+ end
14
+
15
+ def [](app_name)
16
+ system_events.application_processes[app_name]
17
+ end
18
+
19
+ def running_applications
20
+ system_events.application_processes.get.collect { |a| a.name.get }
21
+ end
22
+
23
+ def desktop_size
24
+ @desktop_size ||= Finder.desktop.window.bounds.get
25
+ end
26
+
27
+ def desktop_width
28
+ desktop_size[2]
29
+ end
30
+
31
+ def desktop_height
32
+ desktop_size[3]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'appscript'
3
+
4
+ module Tornado
5
+ VERSION = "0.0.1"
6
+
7
+ def tell(app, &block)
8
+ if block_given?
9
+ app.instance_eval &block
10
+ end
11
+ end
12
+
13
+ def const_missing(name)
14
+ return GenericApplication.find_by_string(name.to_s) || super(name)
15
+ end
16
+
17
+ module Applications; end
18
+ end
19
+
20
+ Object.extend(Tornado)
21
+ extend(Tornado)
22
+
23
+ require 'generic_application'
24
+
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'mocha'
4
+ require 'shoulda'
5
+ require 'tornado'
6
+
7
+ module TestHelpers
8
+ def assert_responds_to(object, *methods)
9
+ methods.each do |m|
10
+ assert object.respond_to?(m), "failed to respond to '#{m}'"
11
+ end
12
+ end
13
+
14
+ def assert_application_not_defined(app_name)
15
+ assert ! application_defined?(app_name)
16
+ end
17
+
18
+ def assert_application_defined(app_name)
19
+ assert application_defined?(app_name)
20
+ end
21
+
22
+ def assert_extension_not_defined(app_name)
23
+ assert ! Tornado::Applications.const_defined?(app_name)
24
+ end
25
+
26
+ def application_defined?(app_name)
27
+ Kernel.const_defined?(app_name)
28
+ end
29
+
30
+ def ensure_application_undefined(app_name)
31
+ Kernel.send(:remove_const, app_name) if application_defined?(app_name)
32
+ end
33
+
34
+ def first_mention_of(*args)
35
+ # called solely for side effect of arguments being mentioned
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ require 'helpers/test_helpers'
2
+
3
+ class ApplicationFinderTest < Test::Unit::TestCase
4
+
5
+ context "The Finder application" do
6
+
7
+ setup do
8
+ Appscript.stubs(:app).returns(mock)
9
+ end
10
+
11
+ should "be able to minimize all windows" do
12
+ Finder.app.expects(:activate)
13
+ mock2 = mock { expects(:set).with(true) }
14
+ mock1 = mock { expects(:collapsed).returns(mock2) }
15
+ Finder.app.expects(:windows).returns(mock1)
16
+ Finder.minimize_all_windows
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,60 @@
1
+ require 'helpers/test_helpers'
2
+
3
+ class ApplicationOSXTest < Test::Unit::TestCase
4
+
5
+ context "The tornado pseudo-app OSX" do
6
+
7
+ should "return the desktop size" do
8
+ bounds = mock { expects(:get).returns([0,0,1440,900]) }
9
+ window = mock { expects(:bounds).returns(bounds) }
10
+ desktop = mock { expects(:window).returns(window) }
11
+ Finder.expects(:desktop).returns(desktop)
12
+ assert_equal [0,0,1440,900], OSX.desktop_size
13
+ end
14
+
15
+ should "use the System Events app" do
16
+ Appscript.expects(:app).with("System Events")
17
+ OSX.instance_variable_set(:@system_events, nil)
18
+ OSX.system_events
19
+ end
20
+
21
+ should "use system events to hide all windows" do
22
+ OSX.system_events.expects(:keystroke).with("h", :using => [ :command_down, :option_down ])
23
+ OSX.hide_everything
24
+ end
25
+
26
+ should "use system events to open urls" do
27
+ OSX.system_events.expects(:open_location).with("foo")
28
+ OSX.open_location("foo")
29
+ end
30
+
31
+ should "use system events to access application processes by name" do
32
+ processes = mock("processes"){ expects(:[] => "Foo") }
33
+ OSX.system_events.expects(:application_processes).returns(processes)
34
+ OSX["Foo"]
35
+ end
36
+
37
+ context "with running applications %w(Foo Bar Baz)" do
38
+
39
+ setup do
40
+ list = [
41
+ stub(:name => stub(:get => "Foo")),
42
+ stub(:name => stub(:get => "Bar")),
43
+ stub(:name => stub(:get => "Baz"))
44
+ ]
45
+ processes = mock() do
46
+ expects(:get).returns(list).at_least_once
47
+ end
48
+ OSX.system_events.expects(:application_processes).returns(processes).at_least_once
49
+ end
50
+
51
+ should "use system events to list application processes by name" do
52
+ list = OSX.running_applications
53
+ assert_equal %w(Foo Bar Baz), list
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,67 @@
1
+ require 'helpers/test_helpers'
2
+
3
+ class ApplicationTerminalTest < Test::Unit::TestCase
4
+
5
+ context "The Terminal application" do
6
+
7
+ context "with a tab" do
8
+
9
+ setup do
10
+ Terminal
11
+ @tab = Tornado::Applications::Terminal::Tab.new(stub)
12
+ end
13
+
14
+ should "be able to call run on tab" do
15
+ Terminal.expects(:do_script).with("foo", :in => @tab.tab)
16
+ @tab.run "foo"
17
+ end
18
+
19
+ should "be able to call clear on tab" do
20
+ @tab.expects(:run).with("clear")
21
+ @tab.clear
22
+ end
23
+
24
+ should "be able to call clear scroll back" do
25
+ @tab.tab.expects(:selected).returns(mock { expects(:set).with(true) })
26
+ Terminal.expects(:keystroke).with("k", :using => :command_down)
27
+ @tab.clear_scrollback
28
+ end
29
+
30
+ should "be able to change directory" do
31
+ @tab.expects(:run).with("cd /path")
32
+ @tab.cd("/path")
33
+ end
34
+
35
+ end
36
+
37
+ context "with mocked out tab" do
38
+
39
+ setup do
40
+ Terminal.expects(:ensure_launched)
41
+ Terminal.expects(:keystroke).with("t", :using => :command_down)
42
+ @tab = mock
43
+ Tornado::Applications::Terminal::Tab.expects(:new).returns(@tab)
44
+ end
45
+
46
+ should "be able to open_new_tab without a path" do
47
+ Terminal.open_new_tab
48
+ end
49
+
50
+ should "be able to open_new_tab with a path" do
51
+ @tab.expects(:cd).with("/path/foo")
52
+ @tab.expects(:clear)
53
+ Terminal.open_new_tab("/path/foo")
54
+ end
55
+
56
+ should "be able to open_new_tab with a block" do
57
+ @tab.expects(:some_method)
58
+ Terminal.open_new_tab do
59
+ some_method
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,125 @@
1
+ require 'helpers/test_helpers'
2
+
3
+ class GenericApplicationTest < Test::Unit::TestCase
4
+ include TestHelpers
5
+
6
+ context "A GenericApplication" do
7
+
8
+ setup do
9
+ Appscript.stubs(:app).returns(mock("app"))
10
+ OSX.stubs(:desktop_size).returns([0, 0, 1024, 768])
11
+ @generic_app = GenericApplication.new(:name => "FakeApplication")
12
+ end
13
+
14
+ should "be able to resize first window with absolute values" do
15
+ bounds = mock { expects(:set).with([100 , 100, 500, 500]) }
16
+ windows = [ mock(:bounds => bounds) ]
17
+ @generic_app.app.expects(:windows).returns(windows)
18
+ @generic_app.expects(:current_bounds).returns([100,100,200,200])
19
+ @generic_app.resize 400, 400
20
+ end
21
+
22
+ should "be able to resize first window with percent values" do
23
+ bounds = mock { expects(:set).with([100 , 100, 612, 484]) }
24
+ windows = [ mock(:bounds => bounds) ]
25
+ @generic_app.app.expects(:windows).returns(windows)
26
+ @generic_app.expects(:current_bounds).returns([100,100,200,200])
27
+ @generic_app.resize "50%", "50%"
28
+ end
29
+
30
+ context "with position bzz" do
31
+ setup do
32
+ @generic_app.stubs(:current_bounds).returns([100,100,200,200])
33
+ @bounds = mock
34
+ windows = [ mock(:bounds => @bounds) ]
35
+ @generic_app.app.expects(:windows).returns(windows)
36
+ end
37
+
38
+ should "be able to position first window in :north_east" do
39
+ @bounds.expects(:set).with([924, 0, 1024, 100])
40
+ @generic_app.position :north_east
41
+ end
42
+
43
+ should "be able to position first window in :south_east" do
44
+ @bounds.expects(:set).with([924, 668, 1024, 768])
45
+ @generic_app.position :south_east
46
+ end
47
+
48
+ should "be able to position first window in :north_west" do
49
+ @bounds.expects(:set).with([0, 0, 100, 100])
50
+ @generic_app.position :north_west
51
+ end
52
+
53
+ should "be able to position first window in :south_west" do
54
+ @bounds.expects(:set).with([0, 668, 100, 768])
55
+ @generic_app.position :south_west
56
+ end
57
+ end
58
+
59
+ should "be able to close all windows" do
60
+ windows = mock("windows") { expects(:close) }
61
+ @generic_app.app.expects(:windows).returns(windows)
62
+ @generic_app.close_all_windows
63
+ end
64
+
65
+ should "be able to minimize all windows" do
66
+ stub_get_true = stub(:get => true, :set => nil)
67
+ stub_get_false = stub(:get => false)
68
+ @generic_app.app.expects(:activate)
69
+ window = mock("window") do
70
+ expects(:visible).returns(stub_get_true).times(3)
71
+ expects(:miniaturized).returns(stub_get_true).times(3)
72
+ end
73
+ non_visible_window = mock("non_visible_window") do
74
+ expects(:visible).returns(stub_get_false)
75
+ expects(:miniaturized).never
76
+ end
77
+ windows = mock(:get => [window, window, window, non_visible_window])
78
+ @generic_app.app.expects(:windows).returns(windows)
79
+ @generic_app.minimize_all_windows
80
+ end
81
+
82
+ should "be able to wait_for_me" do
83
+ @generic_app.expects(:sleep).times(2)
84
+ @generic_app.expects(:is_running?).times(3).returns(false, false, true)
85
+ @generic_app.wait_for_me!
86
+ end
87
+
88
+ should "be able to ensure_launched" do
89
+ @generic_app.expects(:is_running?).returns(false)
90
+ @generic_app.app.expects(:launch)
91
+ @generic_app.expects(:wait_for_me!)
92
+ @generic_app.ensure_launched
93
+ end
94
+
95
+ should "be able to send keystrokes" do
96
+ key, options = "h", { :using => :command_down }
97
+ receiver = mock { expects(:keystroke).with(key, options) }
98
+ OSX.expects(:[]).with("FakeApplication").returns(receiver)
99
+ @generic_app.keystroke(key, options)
100
+ end
101
+
102
+ should "send unrecognized methods to app" do
103
+ @generic_app.app.expects(:a_method_that_does_not_exist)
104
+ @generic_app.a_method_that_does_not_exist
105
+ end
106
+
107
+ end
108
+
109
+ def test_extension_loading_for_app_with_extension
110
+ ensure_application_undefined :Finder
111
+ assert_application_not_defined :Finder
112
+ first_mention_of Finder
113
+ assert_application_defined :Finder
114
+ assert_equal "applications/finder.rb", Finder.extension_path
115
+ assert_equal Tornado::Applications::Finder, Finder.extension
116
+ end
117
+
118
+ def test_extension_loading_for_app_without_extension
119
+ Appscript.stubs(:app).returns(true)
120
+ assert_application_not_defined :ApplicationWithoutExtension
121
+ first_mention_of ApplicationWithoutExtension
122
+ assert_extension_not_defined :ApplicationWithoutExtension
123
+ end
124
+
125
+ end
@@ -0,0 +1,27 @@
1
+ require 'helpers/test_helpers'
2
+
3
+ $main = self
4
+
5
+ class TornadoTest < Test::Unit::TestCase
6
+ include TestHelpers
7
+ include Tornado
8
+
9
+ def test_tell
10
+ $main.respond_to?(:tell)
11
+ Object.new.respond_to?(:tell)
12
+ end
13
+
14
+ def test_automatic_application_reference_based_on_const_missing
15
+ ensure_application_undefined :Terminal
16
+ assert_application_not_defined :Terminal
17
+ first_mention_of Terminal
18
+ assert Terminal.kind_of?(GenericApplication)
19
+ end
20
+
21
+ def test_tell
22
+ fake_app = mock(:nothing => true)
23
+ tell fake_app do
24
+ nothing
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{tornado}
3
+ s.version = "0.0.1"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Jim Garvin"]
7
+ s.date = %q{2009-01-10}
8
+ s.description = %q{Ruby DSL for easily launching, arranging and doing other simple tasks with Mac OS X applications.}
9
+ s.email = %q{jim at thegarvin dot com}
10
+ s.extra_rdoc_files = ["lib/applications/finder.rb", "lib/applications/firefox.rb", "lib/applications/safari.rb", "lib/applications/terminal.rb", "lib/applications/textmate.rb", "lib/generic_application.rb", "lib/osx.rb", "lib/tornado.rb", "README.markdown"]
11
+ s.files = ["examples/tornado-cubenot_site.rb", "lib/applications/finder.rb", "lib/applications/firefox.rb", "lib/applications/safari.rb", "lib/applications/terminal.rb", "lib/applications/textmate.rb", "lib/generic_application.rb", "lib/osx.rb", "lib/tornado.rb", "Manifest", "Rakefile", "README.markdown", "test/helpers/test_helpers.rb", "test/test_application_finder.rb", "test/test_application_osx.rb", "test/test_application_terminal.rb", "test/test_generic_application.rb", "test/test_tornado.rb", "tornado.gemspec"]
12
+ s.has_rdoc = true
13
+ s.homepage = %q{http://github.com/coderifous/tornado}
14
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tornado", "--main", "README.markdown"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{tornado}
17
+ s.rubygems_version = %q{1.2.0}
18
+ s.summary = %q{Ruby DSL for easily launching, arranging and doing other simple tasks with Mac OS X applications.}
19
+ s.test_files = ["test/helpers/test_helpers.rb", "test/test_application_finder.rb", "test/test_application_osx.rb", "test/test_application_terminal.rb", "test/test_generic_application.rb", "test/test_tornado.rb"]
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 2
24
+
25
+ if current_version >= 3 then
26
+ s.add_runtime_dependency(%q<rb-appscript>, [">= 0.5.1"])
27
+ else
28
+ s.add_dependency(%q<rb-appscript>, [">= 0.5.1"])
29
+ end
30
+ else
31
+ s.add_dependency(%q<rb-appscript>, [">= 0.5.1"])
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coderifous-tornado
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jim Garvin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-10 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rb-appscript
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.5.1
23
+ version:
24
+ description: Ruby DSL for easily launching, arranging and doing other simple tasks with Mac OS X applications.
25
+ email: jim at thegarvin dot com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - lib/applications/finder.rb
32
+ - lib/applications/firefox.rb
33
+ - lib/applications/safari.rb
34
+ - lib/applications/terminal.rb
35
+ - lib/applications/textmate.rb
36
+ - lib/generic_application.rb
37
+ - lib/osx.rb
38
+ - lib/tornado.rb
39
+ - README.markdown
40
+ files:
41
+ - examples/tornado-cubenot_site.rb
42
+ - lib/applications/finder.rb
43
+ - lib/applications/firefox.rb
44
+ - lib/applications/safari.rb
45
+ - lib/applications/terminal.rb
46
+ - lib/applications/textmate.rb
47
+ - lib/generic_application.rb
48
+ - lib/osx.rb
49
+ - lib/tornado.rb
50
+ - Manifest
51
+ - Rakefile
52
+ - README.markdown
53
+ - test/helpers/test_helpers.rb
54
+ - test/test_application_finder.rb
55
+ - test/test_application_osx.rb
56
+ - test/test_application_terminal.rb
57
+ - test/test_generic_application.rb
58
+ - test/test_tornado.rb
59
+ - tornado.gemspec
60
+ has_rdoc: true
61
+ homepage: http://github.com/coderifous/tornado
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --line-numbers
65
+ - --inline-source
66
+ - --title
67
+ - Tornado
68
+ - --main
69
+ - README.markdown
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "1.2"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project: tornado
87
+ rubygems_version: 1.2.0
88
+ signing_key:
89
+ specification_version: 2
90
+ summary: Ruby DSL for easily launching, arranging and doing other simple tasks with Mac OS X applications.
91
+ test_files:
92
+ - test/helpers/test_helpers.rb
93
+ - test/test_application_finder.rb
94
+ - test/test_application_osx.rb
95
+ - test/test_application_terminal.rb
96
+ - test/test_generic_application.rb
97
+ - test/test_tornado.rb