osaka 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,9 @@
1
1
 
2
2
  module Osaka
3
3
 
4
+ class InvalidLocation < RuntimeError
5
+ end
6
+
4
7
  class ConditionProxy
5
8
 
6
9
  def initialize(wrapper, action)
@@ -28,37 +31,45 @@ module Osaka
28
31
  end
29
32
 
30
33
  class CheckAction
31
- def execute(wrapper, condition, *args, &block)
32
- wrapper.system_event!("#{condition.as_script(*args)};").strip == "true"
33
- end
34
+ def execute(wrapper, condition, *args, &block)
35
+ wrapper.system_event!("#{condition.as_script(*args)};").strip == "true"
34
36
  end
37
+ end
35
38
 
36
39
  class ExistsCondition
37
- def as_script(element_to_wait_for)
38
- "exists #{element_to_wait_for}"
40
+ def as_script(element_to_check)
41
+ "exists #{element_to_check}"
39
42
  end
40
43
  end
41
44
 
42
45
  class Not_existsCondition
43
- def as_script(element_to_wait_for)
44
- "not exists #{element_to_wait_for}"
46
+ def as_script(element_to_check)
47
+ "not exists #{element_to_check}"
45
48
  end
46
49
  end
47
50
 
48
51
  class ApplicationWrapper
49
52
 
53
+ attr_accessor :window
54
+
50
55
  def initialize(name)
51
56
  @name = name
52
57
  end
53
58
 
59
+ def tell(command)
60
+ ScriptRunner::execute("tell application \"#{@name}\"; #{command}; end tell")
61
+ end
62
+
63
+ def system_event!(event)
64
+ ScriptRunner::execute("tell application \"System Events\"; tell process \"#{@name}\"; #{event}; end tell; end tell")
65
+ end
66
+
54
67
  def print_warning(action, message)
55
68
  puts "Osaka WARNING while doing #{action}: #{message}"
56
69
  end
57
70
 
58
71
  def check_output(output, action)
59
- if (!output.empty?)
60
- print_warning(action, output)
61
- end
72
+ print_warning(action, output) unless output.empty?
62
73
  output
63
74
  end
64
75
 
@@ -67,16 +78,8 @@ module Osaka
67
78
  end
68
79
 
69
80
  def quit
70
- check_output( tell("quit"), "quit" )
71
- end
72
-
73
- def tell(command)
74
- ScriptRunner::execute("tell application \"#{@name}\"; #{command}; end tell")
75
- end
76
-
77
- def system_event!(event)
78
- ScriptRunner::execute("tell application \"System Events\"; tell process \"#{@name}\"; #{event}; end tell; end tell")
79
- end
81
+ keystroke("q", :command)
82
+ end
80
83
 
81
84
  def system_event(event)
82
85
  activate
@@ -92,13 +95,13 @@ module Osaka
92
95
  ConditionProxy.new(self, CheckAction.new)
93
96
  end
94
97
 
95
- def wait_until!
96
- ConditionProxy.new(self, RepeatAction.new)
97
- end
98
+ alias check! check
98
99
 
99
100
  def until!
100
101
  ConditionProxy.new(self, RepeatAction.new)
101
102
  end
103
+
104
+ alias wait_until! until!
102
105
 
103
106
  def construct_modifier_statement(modifier_keys)
104
107
  modified_key_string = [ modifier_keys ].flatten.collect! { |mod_key| mod_key.to_s + " down"}.join(", ")
@@ -113,6 +116,7 @@ module Osaka
113
116
 
114
117
  def keystroke(key, modifier_keys = [])
115
118
  activate
119
+ focus
116
120
  keystroke!(key, modifier_keys)
117
121
  end
118
122
 
@@ -128,16 +132,44 @@ module Osaka
128
132
  end
129
133
 
130
134
  def set!(element, location, value)
131
- check_output( system_event!("set #{element} of #{location} to \"#{value}\""), "set")
135
+ encoded_value = (value.class == String) ? "\"#{value}\"" : value.to_s
136
+ check_output( system_event!("set #{element} of #{location} to #{encoded_value}"), "set")
137
+ end
138
+
139
+ def focus
140
+ current_windows = window_list
141
+ @window = current_windows[0] if @window.nil? || current_windows.index(@window).nil?
142
+ set!("value", "attribute \"AXMain\" of window \"#{window}\"", true) if current_windows[0] != @window
143
+ end
144
+
145
+ def construct_window_info(location)
146
+ location_string = ""
147
+ location_string += " of #{location}" unless location.empty?
148
+ location_string += " of window \"#{window}\"" unless window.nil?
149
+
150
+ raise(Osaka::InvalidLocation, "Invalid location for command:#{location_string}") if location_string.scan("of window").length > 1
151
+
152
+ location_string
132
153
  end
133
154
 
134
- def get!(element, location)
135
- system_event!("get #{element} of #{location}")
155
+ def get!(element, location = "")
156
+ system_event!("get #{element}#{construct_window_info(location)}").strip
157
+ end
158
+
159
+ def get_app!(element)
160
+ system_event!("get #{element}").strip
136
161
  end
137
162
 
138
163
  def set(element, location, value)
139
164
  activate
140
165
  set!(element, location, value)
141
166
  end
167
+
168
+ def window_list
169
+ windows = get_app!("windows").strip.split(',')
170
+ windows.collect { |window|
171
+ window[7...window =~ / of application process/].strip
172
+ }
173
+ end
142
174
  end
143
175
  end
@@ -2,33 +2,37 @@
2
2
  module Osaka
3
3
  module ApplicationWrapperExpectations
4
4
 
5
- def should_wait(wait_command, wait_condition, wait_element)
6
- condition = double(:ConditionAndActionProxy)
7
- @wrapper.should_receive(wait_command).and_return(condition)
8
- condition.should_receive(wait_condition).with(wait_element)
9
- end
10
-
11
5
  def should_wait_until(wait_condition, wait_element)
12
- should_wait(:wait_until, wait_condition, wait_element)
6
+ should_do_with_condition(:wait_until, wait_condition, wait_element)
13
7
  end
14
-
8
+
15
9
  def should_wait_until!(wait_condition, wait_element)
16
- should_wait(:wait_until!, wait_condition, wait_element)
10
+ should_do_with_condition(:wait_until!, wait_condition, wait_element)
17
11
  end
18
-
19
- def should_do_until!(wait_condition, wait_element)
20
- should_wait(:until!, wait_condition, wait_element).and_yield
12
+
13
+ def should_check!(condition, element, return_value)
14
+ should_do_with_condition(:check!, condition, element).and_return(return_value)
15
+ end
16
+
17
+ def should_do_until!(condition, element)
18
+ should_do_with_condition(:until!, condition, element).and_yield
21
19
  yield
22
20
  end
23
-
24
- def expect_keystroke(key, modifier)
25
- @wrapper.should_receive(:keystroke).with(key, modifier).and_return(@wrapper)
21
+
22
+ def expect_keystroke(key, modifier = [])
23
+ @wrapper.should_receive(:keystroke).with(key, modifier).and_return(@wrapper) unless modifier.empty?
24
+ @wrapper.should_receive(:keystroke).with(key).and_return(@wrapper) if modifier.empty?
26
25
  end
27
-
26
+
27
+ def expect_keystroke!(key, modifier = [])
28
+ @wrapper.should_receive(:keystroke!).with(key, modifier).and_return(@wrapper) unless modifier.empty?
29
+ @wrapper.should_receive(:keystroke!).with(key).and_return(@wrapper) if modifier.empty?
30
+ end
31
+
28
32
  def expect_click!(location)
29
33
  @wrapper.should_receive(:click!).with(location).and_return(@wrapper)
30
34
  end
31
-
35
+
32
36
  def expect_click(location)
33
37
  @wrapper.should_receive(:click).with(location).and_return(@wrapper)
34
38
  end
@@ -41,6 +45,13 @@ module Osaka
41
45
  @wrapper.should_receive(:system_event).with(event)
42
46
  end
43
47
 
48
+ private
49
+ def should_do_with_condition(command, condition, element)
50
+ condition_proxy = double(:ConditionAndActionProxy)
51
+ @wrapper.should_receive(command).and_return(condition_proxy)
52
+ condition_proxy.should_receive(condition).with(element)
53
+ end
54
+
44
55
 
45
56
  end
46
57
  end
@@ -0,0 +1,32 @@
1
+
2
+ module Osaka
3
+ class Calculator < TypicalApplication
4
+ attr_accessor :wrapper
5
+
6
+ def initialize
7
+ @name = "Calculator"
8
+ @wrapper = ApplicationWrapper.new("Calculator")
9
+ end
10
+
11
+ def activate
12
+ super
13
+ if (@wrapper.window.nil?)
14
+ wait_for_new_window([])
15
+ @wrapper.window = @wrapper.window_list[0]
16
+ end
17
+ end
18
+
19
+ def click(key)
20
+ @wrapper.click!("button \"#{key}\" of group 2 of window \"#{@name}\"")
21
+ end
22
+
23
+ def key(k)
24
+ @wrapper.keystroke(k)
25
+ end
26
+
27
+ def result
28
+ @wrapper.get!('value', "static text 1 of group 1")
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module Osaka
3
+ class TextEdit < TypicalApplication
4
+ attr_accessor :wrapper
5
+
6
+ def initialize
7
+ @name = "TextEdit"
8
+ @wrapper = ApplicationWrapper.new("TextEdit")
9
+ end
10
+
11
+ def activate
12
+ super
13
+ if (@wrapper.window.nil?)
14
+ wait_for_new_window([])
15
+ @wrapper.window = @wrapper.window_list[0]
16
+ end
17
+ end
18
+
19
+ def type(text)
20
+ @wrapper.keystroke(text)
21
+ end
22
+
23
+ def text
24
+ @wrapper.get!("value", 'text area 1 of scroll area 1')
25
+ end
26
+
27
+ end
28
+ end
@@ -56,27 +56,75 @@ module Osaka
56
56
  }
57
57
  end
58
58
  end
59
+
60
+ class ApplicationInfo
61
+
62
+ attr_reader :name
63
+
64
+ def initialize(script_info)
65
+ @name = script_info.match(/name:(.+?), creation date/)[1]
66
+ end
67
+
68
+ end
59
69
 
60
70
  class TypicalApplication
61
71
 
62
72
  attr_accessor :wrapper
63
73
 
64
74
  def initialize(name)
75
+ @name = name
65
76
  @wrapper = ApplicationWrapper.new(name)
66
77
  end
78
+
79
+ def get_info
80
+ script_info = @wrapper.tell("get info for (path to application \"#{@name}\")")
81
+ ApplicationInfo.new(script_info)
82
+ end
67
83
 
68
84
  def open (filename)
69
85
  abolutePathFileName = File.absolute_path(filename)
70
86
  @wrapper.tell("open \"#{abolutePathFileName}\"")
87
+ @wrapper.window = filename
71
88
  end
72
-
73
- def quit
89
+
90
+ def wait_for_window_and_dialogs_to_close(option)
91
+ if (option != :user_chose)
92
+ @wrapper.until!.not_exists("window \"#{wrapper.window}\"") {
93
+ if (@wrapper.check!.exists("sheet 1 of window \"#{wrapper.window}\""))
94
+ @wrapper.click!("button 2 of sheet 1 of window \"#{wrapper.window}\"")
95
+ end
96
+ }
97
+ end
98
+ end
99
+
100
+ def quit(option = :user_chose)
74
101
  @wrapper.quit
102
+ wait_for_window_and_dialogs_to_close(option)
75
103
  end
76
104
 
105
+ def wait_for_new_window(original_window_list)
106
+ latest_window_list = original_window_list
107
+ while (original_window_list == latest_window_list)
108
+ latest_window_list = @wrapper.window_list
109
+ end
110
+ (latest_window_list - original_window_list)[0]
111
+ end
112
+
113
+ def new_document
114
+ window_list = @wrapper.window_list
115
+ @wrapper.keystroke("n", :command)
116
+ @wrapper.window = wait_for_new_window(window_list)
117
+ @wrapper.focus
118
+ end
119
+
77
120
  def save
78
121
  @wrapper.keystroke("s", :command)
79
122
  end
123
+
124
+ def close(option = :user_chose)
125
+ @wrapper.keystroke("w", :command)
126
+ wait_for_window_and_dialogs_to_close(option)
127
+ end
80
128
 
81
129
  def activate
82
130
  @wrapper.activate
@@ -87,7 +135,7 @@ module Osaka
87
135
  end
88
136
 
89
137
  def print_dialog
90
- location = "sheet 1 of window 1"
138
+ location = "sheet 1#{@wrapper.construct_window_info}"
91
139
  @wrapper.keystroke("p", :command).wait_until.exists(location)
92
140
  create_print_dialog(location)
93
141
  end
data/lib/osaka/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Osaka
3
- VERSION = "0.2.2"
3
+ VERSION = "0.2.3"
4
4
  end
data/lib/osaka.rb CHANGED
@@ -6,3 +6,6 @@ require 'osaka/typicalapplication'
6
6
  require 'osaka/pages'
7
7
  require 'osaka/numbers'
8
8
  require 'osaka/keynote'
9
+ require 'osaka/calculator'
10
+ require 'osaka/textedit'
11
+
@@ -27,26 +27,16 @@ describe "Osaka::ApplicationWrapper" do
27
27
  subject.print_warning("action", "Message")
28
28
  end
29
29
 
30
- it "Has a short-cut method for activation" do
31
- Osaka::ScriptRunner.should_receive(:execute).with(/activate/).and_return("")
32
- subject.activate
33
- end
34
-
35
30
  it "Should print an Warning message with the ScriptRunner returns text when doing activate" do
36
31
  check_for_warning("activate")
37
32
  subject.activate
38
33
  end
39
34
 
40
35
  it "Has a short-cut method for quitting" do
41
- Osaka::ScriptRunner.should_receive(:execute).with(/quit/).and_return("")
36
+ subject.should_receive(:keystroke).with("q", :command)
42
37
  subject.quit
43
38
  end
44
39
 
45
- it "Prints a warning message when quit results in some output" do
46
- check_for_warning("quit")
47
- subject.quit
48
- end
49
-
50
40
  it "Should be able to generate events via the Systems Events" do
51
41
  Osaka::ScriptRunner.should_receive(:execute).with(/tell application "System Events"; tell process #{quoted_name}; quit; end tell; end tell/)
52
42
  subject.system_event!("quit")
@@ -95,6 +85,7 @@ describe "Osaka::ApplicationWrapper" do
95
85
 
96
86
  it "Should be able to keystroke and activate" do
97
87
  subject.should_receive(:activate)
88
+ subject.should_receive(:focus)
98
89
  subject.should_receive(:keystroke!).with("a", [])
99
90
  subject.keystroke("a", [])
100
91
  end
@@ -117,6 +108,7 @@ describe "Osaka::ApplicationWrapper" do
117
108
 
118
109
  it "Should be able to keystroke_and_wait_until_exists and activate" do
119
110
  subject.should_receive(:activate)
111
+ subject.should_receive(:focus)
120
112
  Osaka::ScriptRunner.should_receive(:execute).with(/keystroke "p"/).and_return("")
121
113
  Osaka::ScriptRunner.should_receive(:execute).with(/exists window 1/).and_return("true")
122
114
  subject.keystroke("p", []).wait_until!.exists("window 1")
@@ -147,26 +139,53 @@ describe "Osaka::ApplicationWrapper" do
147
139
  end
148
140
 
149
141
  it "Should be able to set a value to an element" do
150
- check_for_warning("set")
142
+ subject.should_receive(:system_event!).with(/set value of window to "newvalue"/).and_return("")
151
143
  subject.set!("value", "window", "newvalue")
152
144
  end
153
145
 
154
146
  it "Prints a warning when setting and element and output is received" do
155
- subject.should_receive(:system_event!).with(/set value of window to "newvalue"/).and_return("")
147
+ check_for_warning("set")
156
148
  subject.set!("value", "window", "newvalue")
157
149
  end
158
150
 
151
+ it "Should be able to set to boolean values" do
152
+ subject.should_receive(:system_event!).with(/set value of window to true/).and_return("")
153
+ subject.set!("value", "window", true)
154
+ end
155
+
159
156
  it "Should be able to get a value from an element" do
160
- subject.should_receive(:system_event!).with(/get value of window/).and_return("1")
157
+ subject.should_receive(:system_event!).with(/get value of window/).and_return("1\n")
161
158
  subject.get!("value", "window").should == "1"
162
159
  end
163
160
 
161
+ it "Should use the locally stored window when that one is set." do
162
+ subject.window = "1"
163
+ subject.should_receive(:system_event!).with(/get value of window \"1\"/).and_return("1\n")
164
+ subject.get!("value").should == "1"
165
+ end
166
+
167
+ it "Should throw an exception when window is set multiple times." do
168
+ subject.window = "Untitled"
169
+ lambda {subject.get!("value", "window 1")}.should raise_error(Osaka::InvalidLocation, "Invalid location for command: of window 1 of window \"Untitled\"")
170
+ end
171
+
172
+ it "Should combine the location and the window" do
173
+ subject.window = "1"
174
+ subject.should_receive(:system_event!).with(/get value of dialog 2 of window "1"/).and_return("1\n")
175
+ subject.get!("value", "dialog 2").should == "1"
176
+ end
177
+
178
+ it "Should be able to get values from the application itself" do
179
+ subject.should_receive(:system_event!).with("get value").and_return("1\n")
180
+ subject.get_app!("value").should == "1"
181
+ end
182
+
164
183
  it "Should be able to set a value and activate" do
165
184
  subject.should_receive(:activate)
166
185
  subject.should_receive(:set!).with("value", "window", "newvalue")
167
186
  subject.set("value", "window", "newvalue")
168
187
  end
169
-
188
+
170
189
  it "Should be able to loop over some script until something happens" do
171
190
  counter = 0
172
191
  Osaka::ScriptRunner.should_receive(:execute).exactly(3).times.with(/exists window/).and_return {
@@ -183,4 +202,53 @@ describe "Osaka::ApplicationWrapper" do
183
202
  }
184
203
  end
185
204
 
205
+ it "Should be able to get an empty array when requesting for the window list and there are none" do
206
+ subject.should_receive(:get_app!).with("windows").and_return("\n")
207
+ subject.window_list.should == []
208
+ end
209
+
210
+ it "Should be able get an array with one window name when there is exactly one window" do
211
+ subject.should_receive(:get_app!).with("windows").and_return("window one of application process process\n")
212
+ subject.window_list.should == ["one"]
213
+ end
214
+
215
+ it "Should be able to get an array of multiple window names" do
216
+ subject.should_receive(:get_app!).with("windows").and_return("window one of application process process, window two of application process process\n")
217
+ subject.window_list.should == ["one", "two"]
218
+ end
219
+
220
+ it "Should initialize the current window when it is not focused yet" do
221
+ subject.should_receive(:window_list).and_return(["1"])
222
+ subject.focus
223
+ subject.window.should == "1"
224
+ end
225
+
226
+ it "Shouldn't initialize current window when it is already set" do
227
+ subject.should_receive(:window_list).and_return(["1"])
228
+ subject.focus
229
+
230
+ subject.should_receive(:window_list).and_return(["2", "1"])
231
+ subject.should_receive(:set!)
232
+ subject.focus
233
+ subject.window.should == "1"
234
+ end
235
+
236
+ it "Should re-initialize the current window when it doesn't exist anymore" do
237
+ subject.should_receive(:window_list).and_return(["1"])
238
+ subject.focus
239
+
240
+ subject.should_receive(:window_list).and_return(["2"])
241
+ subject.focus
242
+ subject.window.should == "2"
243
+ end
244
+
245
+ it "Should focus the current window when it doesn't have focus" do
246
+ subject.should_receive(:window_list).and_return(["1"])
247
+ subject.focus
248
+
249
+ subject.should_receive(:window_list).and_return(["2", "1"])
250
+ subject.should_receive(:set!).with("value", "attribute \"AXMain\" of window \"1\"", true )
251
+ subject.focus
252
+ end
253
+
186
254
  end
@@ -0,0 +1,47 @@
1
+
2
+ require 'osaka'
3
+
4
+ describe "Mac GUI Calculator" do
5
+
6
+ include(*Osaka::ApplicationWrapperExpectations)
7
+
8
+ subject { Osaka::Calculator.new }
9
+
10
+ before (:each) do
11
+ @wrapper = subject.wrapper = double("Osaka::ApplicationWrapper")
12
+ end
13
+
14
+ it "Should be setting the window when starting the Calculator" do
15
+
16
+ # TODO: Fix this duplication between this and TextEdit.
17
+
18
+ @wrapper.should_receive(:activate)
19
+ @wrapper.should_receive(:window).and_return(nil)
20
+ subject.should_receive(:wait_for_new_window).with([])
21
+ @wrapper.should_receive(:window_list).and_return(["Calculator"])
22
+ @wrapper.should_receive(:window=).with("Calculator")
23
+ subject.activate
24
+ end
25
+
26
+
27
+ it "Should be able to click a button on the calculator" do
28
+ expect_click!('button "1" of group 2 of window "Calculator"')
29
+ subject.click("1")
30
+ end
31
+
32
+ it "Should be able to use keystroke on the calculator" do
33
+ expect_keystroke("1")
34
+ subject.key("1")
35
+ end
36
+
37
+ it "Should be able to quit the calculator" do
38
+ @wrapper.should_receive(:quit)
39
+ subject.quit
40
+ end
41
+
42
+ it "Should be able to get the value from the screen" do
43
+ @wrapper.should_receive(:get!).with("value", 'static text 1 of group 1').and_return("0")
44
+ subject.result.should == "0"
45
+ end
46
+
47
+ end
@@ -0,0 +1,43 @@
1
+
2
+ require 'osaka'
3
+
4
+ describe "Integration test using the Calculator" do
5
+
6
+ subject { Osaka::Calculator.new }
7
+
8
+ before (:each) do
9
+ subject.activate
10
+ end
11
+
12
+ after (:each) do
13
+ subject.quit
14
+ end
15
+
16
+ it "Should be able to get info from the calculator" do
17
+ app_info = subject.get_info
18
+
19
+ end
20
+
21
+ it "Should be able to do calculations with mouse" do
22
+ subject.click("1")
23
+ subject.click("+")
24
+ subject.click("1")
25
+ subject.click("=")
26
+ subject.result.should == "2"
27
+ end
28
+
29
+ it "Should be able to do calculations using keyboard" do
30
+ subject.key("10")
31
+ subject.key("*")
32
+ subject.key("10")
33
+ subject.key("=")
34
+ subject.result.should == "100"
35
+ end
36
+
37
+ it "Should do whole formulas using key" do
38
+ subject.key("100+10*3+99=")
39
+ sleep 0.5
40
+ subject.result.should == "229"
41
+ end
42
+
43
+ end
@@ -0,0 +1,38 @@
1
+
2
+ require 'osaka'
3
+
4
+ describe "Integration test using TextEdit" do
5
+
6
+ subject { Osaka::TextEdit.new }
7
+
8
+ before (:each) do
9
+ end
10
+
11
+ after (:each) do
12
+ subject.quit(:dont_save)
13
+ end
14
+
15
+ it "can type in the window" do
16
+ subject.activate
17
+ subject.type("Hello World")
18
+ subject.text.should == "Hello World"
19
+ end
20
+
21
+ it "can type in two windows using two instances" do
22
+ editor1 = subject
23
+ editor2 = Osaka::TextEdit.new
24
+
25
+ editor1.activate
26
+ editor2.new_document
27
+
28
+ editor1.type("Typing in window 1")
29
+ editor2.type("Typing in window 2")
30
+
31
+ editor1.text.should == "Typing in window 1"
32
+ editor2.text.should == "Typing in window 2"
33
+
34
+ editor1.close(:dont_save)
35
+ editor2.close(:dont_save)
36
+ end
37
+
38
+ end
@@ -0,0 +1,39 @@
1
+
2
+ require 'osaka'
3
+
4
+ describe "TextEdit" do
5
+
6
+ include(*Osaka::ApplicationWrapperExpectations)
7
+
8
+ subject { Osaka::TextEdit.new }
9
+
10
+ before (:each) do
11
+ @wrapper = subject.wrapper = double("Osaka::ApplicationWrapper")
12
+ end
13
+
14
+ it "should set the window on activation" do
15
+ @wrapper.should_receive(:activate)
16
+ @wrapper.should_receive(:window).and_return(nil)
17
+ subject.should_receive(:wait_for_new_window).with([])
18
+ @wrapper.should_receive(:window_list).and_return(["Untitled"])
19
+ @wrapper.should_receive(:window=).with("Untitled")
20
+ subject.activate
21
+ end
22
+
23
+ it "shouldn't set the window on activation when it is already set" do
24
+ @wrapper.should_receive(:activate)
25
+ @wrapper.should_receive(:window).and_return("Untitled")
26
+ subject.activate
27
+ end
28
+
29
+ it "Should be able to type some text" do
30
+ expect_keystroke('Hello World')
31
+ subject.type("Hello World")
32
+ end
33
+
34
+ it "Should be able to get the text from the document" do
35
+ subject.wrapper.should_receive(:get!).with("value", 'text area 1 of scroll area 1').and_return("Hello")
36
+ subject.text.should == "Hello"
37
+ end
38
+
39
+ end
@@ -14,6 +14,7 @@ describe "Osaka::TypicalApplication" do
14
14
  it "Should pass the right open string to the Keynote application osascript" do
15
15
  filename = "filename.key"
16
16
  expect_tell("open \"#{File.absolute_path(filename)}\"")
17
+ @wrapper.should_receive(:window=).with(filename)
17
18
  subject.open(filename)
18
19
  end
19
20
 
@@ -22,11 +23,56 @@ describe "Osaka::TypicalApplication" do
22
23
  subject.quit
23
24
  end
24
25
 
26
+ it "Should be able to quit without saving" do
27
+ @wrapper.should_receive(:window).any_number_of_times.and_return("Untitled")
28
+ @wrapper.should_receive(:quit)
29
+ should_do_until!(:not_exists, "window \"Untitled\"") {
30
+ should_check!(:exists, "sheet 1 of window \"Untitled\"", true)
31
+ expect_click!('button 2 of sheet 1 of window "Untitled"')
32
+ }
33
+ subject.quit(:dont_save)
34
+ end
35
+
36
+ it "Should be able to wait until a new window exists" do
37
+ subject.wrapper.should_receive(:window_list).and_return(["new window"])
38
+ subject.wait_for_new_window([])
39
+ end
40
+
41
+ it "Should be able to wait until a new window exists and it takes 4 calls" do
42
+ counter = 0
43
+ subject.wrapper.should_receive(:window_list).exactly(4).times.and_return(["new window"]) {
44
+ counter = counter + 1
45
+ counter.should <= 5 # Added here so that the test won't end up in an endless loop.
46
+ counter >= 4 ? [ "new window" ] : []
47
+ }
48
+ subject.wait_for_new_window([])
49
+ end
50
+
51
+ it "Should be able to create a new document" do
52
+ subject.wrapper.should_receive(:window_list)
53
+ expect_keystroke("n", :command)
54
+ subject.should_receive(:wait_for_new_window).and_return("new_window")
55
+ subject.wrapper.should_receive(:window=).with("new_window")
56
+ subject.wrapper.should_receive(:focus)
57
+ subject.new_document
58
+ end
59
+
25
60
  it "Should be able to save" do
26
61
  expect_keystroke("s", :command)
27
62
  subject.save
28
63
  end
29
64
 
65
+ it "Should be able to close" do
66
+ expect_keystroke("w", :command)
67
+ subject.close
68
+ end
69
+
70
+ it "Should be able to close and don't save" do
71
+ expect_keystroke("w", :command)
72
+ subject.should_receive(:wait_for_window_and_dialogs_to_close).with(:dont_save)
73
+ subject.close(:dont_save)
74
+ end
75
+
30
76
  it "Should be able to activate keynote" do
31
77
  @wrapper.should_receive(:activate)
32
78
  subject.activate
@@ -34,9 +80,18 @@ describe "Osaka::TypicalApplication" do
34
80
 
35
81
  it "Should be able to retrieve a print dialog" do
36
82
  expect_keystroke("p", :command)
83
+ @wrapper.should_receive(:construct_window_info).and_return(" of window 1")
37
84
  should_wait_until(:exists, "sheet 1 of window 1")
38
85
  subject.print_dialog
39
- end
86
+ end
87
+
88
+ describe "Application info" do
89
+ it "Should be able to retrieve an application info object and parse it" do
90
+ @wrapper.should_receive(:tell).with('get info for (path to application "ApplicationName")').and_return('name:ApplicationName.app, creation date:date "Sunday, December 21, 2008 PM 06:14:11"}')
91
+ app_info = subject.get_info
92
+ app_info.name.should == "ApplicationName.app"
93
+ end
94
+ end
40
95
 
41
96
  describe "Generic Print Dialog" do
42
97
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: osaka
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.2
5
+ version: 0.2.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Bas Vodde
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-02-26 00:00:00 +08:00
13
+ date: 2012-04-14 00:00:00 +08:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -49,18 +49,24 @@ files:
49
49
  - lib/osaka.rb
50
50
  - lib/osaka/applicationwrapper.rb
51
51
  - lib/osaka/applicationwrapperexpectations.rb
52
+ - lib/osaka/calculator.rb
52
53
  - lib/osaka/keynote.rb
53
54
  - lib/osaka/numbers.rb
54
55
  - lib/osaka/pages.rb
55
56
  - lib/osaka/scriptrunner.rb
57
+ - lib/osaka/textedit.rb
56
58
  - lib/osaka/typicalapplication.rb
57
59
  - lib/osaka/version.rb
58
60
  - osaka.gemfile
59
61
  - spec/applicationwrapper_spec.rb
62
+ - spec/calculator_spec.rb
63
+ - spec/integration_calculator_spec.rb
64
+ - spec/integration_textedit_spec.rb
60
65
  - spec/keynote_spec.rb
61
66
  - spec/numbers_spec.rb
62
67
  - spec/pages_spec.rb
63
68
  - spec/scriptrunner_spec.rb
69
+ - spec/textedit_spec.rb
64
70
  - spec/typicalapplication_spec.rb
65
71
  has_rdoc: true
66
72
  homepage: https://github.com/basvodde/osaka