osaka 0.2.2 → 0.2.3

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,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