osaka 0.4.8 → 0.4.10

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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +7 -0
  3. data/README.rdoc +1 -1
  4. data/Rakefile +12 -2
  5. data/lib/osaka.rb +6 -0
  6. data/lib/osaka/calculator.rb +1 -1
  7. data/lib/osaka/commandrunner.rb +17 -0
  8. data/lib/osaka/defaultssystem.rb +28 -0
  9. data/lib/osaka/keynote.rb +8 -6
  10. data/lib/osaka/keynoteflow.rb +10 -2
  11. data/lib/osaka/launchservices.rb +29 -0
  12. data/lib/osaka/location.rb +1 -1
  13. data/lib/osaka/mailmergeflow.rb +1 -1
  14. data/lib/osaka/numbers.rb +1 -1
  15. data/lib/osaka/osakaexpectations.rb +65 -61
  16. data/lib/osaka/pages.rb +35 -26
  17. data/lib/osaka/preview.rb +1 -1
  18. data/lib/osaka/remotecontrol.rb +57 -47
  19. data/lib/osaka/scriptrunner.rb +2 -11
  20. data/lib/osaka/textedit.rb +1 -1
  21. data/lib/osaka/typicalapplication.rb +10 -4
  22. data/lib/osaka/typicalfinderdialog.rb +1 -1
  23. data/lib/osaka/typicalopendialog.rb +22 -18
  24. data/lib/osaka/typicalprintdialog.rb +1 -1
  25. data/lib/osaka/typicalsavedialog.rb +1 -1
  26. data/lib/osaka/version.rb +1 -1
  27. data/{osaka.gemfile → osaka.gemspec} +0 -0
  28. data/spec/assets/document.pdf +0 -0
  29. data/spec/calculator_spec.rb +5 -5
  30. data/spec/defaultssystem_spec.rb +30 -0
  31. data/spec/integration_calculator_spec.rb +7 -7
  32. data/spec/integration_keynote_spec.rb +24 -11
  33. data/spec/integration_numbers_spec.rb +2 -2
  34. data/spec/integration_pages_numbers_mail_merge_spec.rb +9 -9
  35. data/spec/integration_preview_spec.rb +16 -0
  36. data/spec/integration_textedit_spec.rb +5 -5
  37. data/spec/keynote_flows_spec.rb +52 -31
  38. data/spec/keynote_spec.rb +24 -14
  39. data/spec/launchservices_spec.rb +63 -0
  40. data/spec/location_spec.rb +13 -13
  41. data/spec/mailmergeflow_spec.rb +13 -13
  42. data/spec/numbers_spec.rb +10 -10
  43. data/spec/osakaexpectations_spec.rb +3 -3
  44. data/spec/pages_spec.rb +80 -61
  45. data/spec/preview_spec.rb +5 -5
  46. data/spec/remotecontrol_spec.rb +65 -43
  47. data/spec/scriptrunner_spec.rb +22 -22
  48. data/spec/textedit_spec.rb +3 -3
  49. data/spec/typicalapplication_spec.rb +119 -108
  50. data/spec/typicalfinderdialog_spec.rb +2 -2
  51. data/spec/typicalopendialog_spec.rb +41 -35
  52. data/spec/typicalprintdialog_spec.rb +5 -5
  53. data/spec/typicalsavedialog_spec.rb +10 -10
  54. metadata +51 -47
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 854d5b4239636f0440e333079786058eb04104d5
4
+ data.tar.gz: 05d82bb53d115828c0545585288c1d5c155097ff
5
+ SHA512:
6
+ metadata.gz: 98ac0bf615f682f2fe15913e42c4785bff36a0635e46745a43fc4c4d6329f1e5d3529ed7539727a4e8c69f2f31ef888f5f109926ea9b9ddf26e3f5e167b948ce
7
+ data.tar.gz: abb76f7009b18c85e62847f563a3aa6384e4ebfa742d24396dbeee73de36c7fd6cb140adca7d7c90e0622a059d354e28949361e7e8382067ad25f9bbd62b6188
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rspec', '~> 3.1'
7
+ end
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
2
  Osaka - apple OSA script Kontrolling the Application (OSAKA :P)
3
- This is a Ruby 1.9 library for automating work via GUI on Mac (using OSA/Applescript)
3
+ This is a Ruby library for automating work via GUI on Mac (using OSA/Applescript)
4
4
 
5
5
  = How to install
6
6
 
data/Rakefile CHANGED
@@ -1,6 +1,16 @@
1
1
  #!/usr/bin/env rake
2
2
  require 'rspec/core/rake_task'
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
4
+ task :default => :all
5
5
 
6
- task :default => :spec
6
+ desc "Run the spec tasks"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.rspec_opts = ["--tag ~integration"]
9
+ end
10
+
11
+ desc "Run the integration tests"
12
+ RSpec::Core::RakeTask.new(:integration) do |t|
13
+ t.rspec_opts = ["--tag integration"]
14
+ end
15
+
16
+ RSpec::Core::RakeTask.new(:all)
data/lib/osaka.rb CHANGED
@@ -1,5 +1,11 @@
1
1
 
2
+ # Non UI servies
3
+ require 'osaka/commandrunner'
2
4
  require 'osaka/scriptrunner'
5
+ require 'osaka/launchservices'
6
+ require 'osaka/defaultssystem'
7
+
8
+ # Basic UI automation
3
9
  require 'osaka/location'
4
10
  require 'osaka/remotecontrol'
5
11
  require 'osaka/typicalapplication'
@@ -31,4 +31,4 @@ module Osaka
31
31
  control.get!('value', at.static_text(1).group(1))
32
32
  end
33
33
  end
34
- end
34
+ end
@@ -0,0 +1,17 @@
1
+
2
+ # encoding: utf-8
3
+
4
+ module Osaka
5
+
6
+ class SystemCommandFailed < RuntimeError
7
+ end
8
+
9
+ module CommandRunner
10
+ def self.run(command)
11
+ output = `#{command} 2>&1`
12
+ raise Osaka::SystemCommandFailed, "message" + output unless $?.success?
13
+ output
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,28 @@
1
+ require 'json'
2
+
3
+ class DefaultsSystem
4
+
5
+
6
+ def initialize(domain)
7
+ @domain = domain
8
+ @settings = {}
9
+ parse_settings_file(Osaka::CommandRunner.run("defaults read #{domain}"))
10
+ end
11
+
12
+ def parse_settings_file (settings_from_defaults)
13
+ scanner = StringScanner.new (settings_from_defaults)
14
+ scanner.scan(/{\n/)
15
+ while scanner.scan(/\s+(.*) = (.*);\n/) do
16
+ @settings[scanner[1]] = scanner[2]
17
+ end
18
+ end
19
+
20
+ def [](key)
21
+ @settings[key]
22
+ end
23
+
24
+ def []=(key, value)
25
+ Osaka::CommandRunner.run("defaults write #{@domain} #{key} #{value}")
26
+ end
27
+
28
+ end
data/lib/osaka/keynote.rb CHANGED
@@ -16,12 +16,14 @@ module Osaka
16
16
  end
17
17
 
18
18
  def select_all_slides
19
- if control.exists?(at.button("Slides").group(1).outline(1).scroll_area(2).splitter_group(1).splitter_group(1))
20
- control.click(at.button("Slides").group(1).outline(1).scroll_area(2).splitter_group(1).splitter_group(1))
21
- else
22
- control.click(at.button("Slides").group(1).outline(1).scroll_area(1).splitter_group(1).splitter_group(1))
23
- end
19
+ light_table_view
24
20
  select_all
25
21
  end
22
+
23
+ def light_table_view
24
+ if control.exists?(at.menu_item("Light Table").menu(1).menu_bar_item("View").menu_bar(1))
25
+ control.click(at.menu_item("Light Table").menu(1).menu_bar_item("View").menu_bar(1))
26
+ end
27
+ end
26
28
  end
27
- end
29
+ end
@@ -1,22 +1,29 @@
1
1
 
2
2
  module CommonFlows
3
+
3
4
  def self.keynote_combine_files(result_file, files_to_merge)
4
5
  keynote = Osaka::Keynote.new
6
+ keynote.activate
7
+ keynote.raise_error_on_open_standard_windows("All Keynote windows must be closed before running this flow")
8
+
5
9
  files_to_merge = [files_to_merge].flatten
6
10
  keynote.open(files_to_merge.shift)
11
+ keynote.light_table_view
7
12
  keynote.save_as(result_file)
8
13
 
14
+
9
15
  files_to_merge.each { |file|
10
16
  combine_keynote = Osaka::Keynote.new
11
17
  combine_keynote.open(file)
12
18
  combine_keynote.select_all_slides
13
19
  combine_keynote.copy
20
+ combine_keynote.close
14
21
  keynote.select_all_slides
15
22
  keynote.paste
16
- combine_keynote.close
17
23
  }
18
24
 
19
25
  keynote.save
26
+ keynote.close
20
27
  keynote.quit
21
28
  end
22
29
 
@@ -26,4 +33,5 @@ module CommonFlows
26
33
  files_to_open = files_in_directory.collect { |f| File.join(directory, f)}
27
34
  keynote_combine_files(result_file, files_to_open.sort)
28
35
  end
29
- end
36
+
37
+ end
@@ -0,0 +1,29 @@
1
+
2
+ module Osaka
3
+ module LaunchServices
4
+
5
+ def self.dump
6
+ Osaka::CommandRunner.run("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump")
7
+ end
8
+
9
+ def self.retrieve(bundle_name)
10
+ launch_services_dump = Osaka::CommandRunner.run("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump")
11
+ current_hash = {}
12
+ launch_services_hash = {}
13
+
14
+ launch_services_dump.each_line do |line|
15
+ if line =~ /^(\w.*):\s+(\w.*)$/
16
+ launch_services_hash[current_hash[:name]] = current_hash
17
+ current_hash = {:id => $2}
18
+ end
19
+ if line =~ /^\t(\w.*):\s+(\w.*)$/
20
+ current_hash[$1.to_sym] = $2
21
+ #puts current_hash
22
+ end
23
+ end
24
+ launch_services_hash[current_hash[:name]] = current_hash
25
+ launch_services_hash[bundle_name]
26
+ end
27
+
28
+ end
29
+ end
@@ -153,4 +153,4 @@ end
153
153
 
154
154
  def at
155
155
  Osaka::Location.new ""
156
- end
156
+ end
@@ -16,4 +16,4 @@ module CommonFlows
16
16
  pages.close(:dont_save)
17
17
  pages.quit(:dont_save)
18
18
  end
19
- end
19
+ end
data/lib/osaka/numbers.rb CHANGED
@@ -50,4 +50,4 @@ module Osaka
50
50
 
51
51
 
52
52
  end
53
- end
53
+ end
@@ -1,132 +1,136 @@
1
1
 
2
2
  module Osaka
3
3
  module OsakaExpectations
4
-
4
+
5
5
  def simulate_mac_version(version)
6
- control.should_receive(:mac_version).and_return(version)
6
+ expect(control).to receive(:mac_version).and_return(version)
7
7
  end
8
-
8
+
9
9
  def expect_execute_osascript(command = nil)
10
- return Osaka::ScriptRunner.should_receive(:execute).with(command) unless command.nil?
11
- Osaka::ScriptRunner.should_receive(:execute)
10
+ return expect(Osaka::ScriptRunner).to receive(:execute).with(command) unless command.nil?
11
+ expect(Osaka::ScriptRunner).to receive(:execute)
12
12
  end
13
-
13
+
14
14
  def expect_clone
15
- control.should_receive(:clone)
15
+ expect(control).to receive(:clone)
16
16
  end
17
-
17
+
18
18
  def expect_activate
19
- control.should_receive(:activate)
19
+ expect(control).to receive(:activate)
20
20
  end
21
21
 
22
22
  def expect_launch
23
- control.should_receive(:launch)
23
+ expect(control).to receive(:launch)
24
24
  end
25
-
25
+
26
26
  def expect_focus
27
- control.should_receive(:focus)
27
+ expect(control).to receive(:focus)
28
28
  end
29
29
 
30
30
  def expect_focus!
31
- control.should_receive(:focus!)
31
+ expect(control).to receive(:focus!)
32
32
  end
33
-
33
+
34
34
  def expect_set_current_window(name)
35
- control.should_receive(:set_current_window).with(name)
35
+ expect(control).to receive(:set_current_window).with(name)
36
36
  end
37
-
37
+
38
38
  def expect_running?
39
- control.should_receive(:running?)
39
+ expect(control).to receive(:running?)
40
40
  end
41
-
41
+
42
42
  def expect_quit
43
- control.should_receive(:quit)
43
+ expect(control).to receive(:quit)
44
44
  end
45
-
45
+
46
46
  def expect_window_list
47
- control.should_receive(:window_list)
47
+ expect(control).to receive(:window_list)
48
+ end
49
+
50
+ def expect_standard_window_list
51
+ expect(control).to receive(:standard_window_list)
48
52
  end
49
-
53
+
50
54
  def expect_current_window_name
51
- control.should_receive(:current_window_name)
55
+ expect(control).to receive(:current_window_name)
52
56
  end
53
-
57
+
54
58
  def expect_set(element, location, value)
55
- control.should_receive(:set).with(element, location, value)
59
+ expect(control).to receive(:set).with(element, location, value)
56
60
  end
57
61
 
58
62
  def expect_set!(element, location, value)
59
- control.should_receive(:set!).with(element, location, value)
63
+ expect(control).to receive(:set!).with(element, location, value)
60
64
  end
61
-
65
+
62
66
  def expect_get_app!(element)
63
- control.should_receive(:get_app!).with(element)
67
+ expect(control).to receive(:get_app!).with(element)
64
68
  end
65
-
69
+
66
70
  def expect_keystroke(key, modifier = [])
67
- control.should_receive(:keystroke).with(key, modifier).and_return(control) unless modifier.empty?
68
- control.should_receive(:keystroke).with(key).and_return(control) if modifier.empty?
71
+ expect(control).to receive(:keystroke).with(key, modifier).and_return(control) unless modifier.empty?
72
+ expect(control).to receive(:keystroke).with(key).and_return(control) if modifier.empty?
69
73
  end
70
-
74
+
71
75
  def expect_keystroke!(key, modifier = [])
72
- control.should_receive(:keystroke!).with(key, modifier).and_return(control) unless modifier.empty?
73
- control.should_receive(:keystroke!).with(key).and_return(control) if modifier.empty?
76
+ expect(control).to receive(:keystroke!).with(key, modifier).and_return(control) unless modifier.empty?
77
+ expect(control).to receive(:keystroke!).with(key).and_return(control) if modifier.empty?
74
78
  end
75
-
79
+
76
80
  def expect_click!(location)
77
- control.should_receive(:click!).with(location).and_return(control)
81
+ expect(control).to receive(:click!).with(location).and_return(control)
78
82
  end
79
-
83
+
80
84
  def expect_click(location)
81
- control.should_receive(:click).with(location).and_return(control)
85
+ expect(control).to receive(:click).with(location).and_return(control)
82
86
  end
83
-
87
+
84
88
  def expect_click_menu_bar(menu_item, menu_name)
85
- control.should_receive(:click_menu_bar).with(menu_item, menu_name).and_return(control)
89
+ expect(control).to receive(:click_menu_bar).with(menu_item, menu_name).and_return(control)
86
90
  end
87
-
91
+
88
92
  def expect_get!(element, location)
89
- control.should_receive(:get!).with(element, location)
93
+ expect(control).to receive(:get!).with(element, location)
90
94
  end
91
-
95
+
92
96
  def expect_tell(do_this)
93
- control.should_receive(:tell).with(do_this)
97
+ expect(control).to receive(:tell).with(do_this)
94
98
  end
95
-
99
+
96
100
  def expect_system_event(event)
97
- control.should_receive(:system_event).with(event)
101
+ expect(control).to receive(:system_event).with(event)
98
102
  end
99
103
 
100
104
  def expect_system_event!(event)
101
- control.should_receive(:system_event!).with(event)
105
+ expect(control).to receive(:system_event!).with(event)
102
106
  end
103
-
107
+
104
108
  def expect_exists?(location)
105
- control.should_receive(:exists?).with(location)
109
+ expect(control).to receive(:exists?).with(location)
106
110
  end
107
-
111
+
108
112
  def expect_not_exists?(location)
109
- control.should_receive(:not_exists?).with(location)
113
+ expect(control).to receive(:not_exists?).with(location)
110
114
  end
111
-
115
+
112
116
  def expect_wait_until_exists(*location)
113
- control.should_receive(:wait_until_exists).with(*location)
117
+ expect(control).to receive(:wait_until_exists).with(*location)
114
118
  end
115
119
 
116
120
  def expect_wait_until_exists!(*location)
117
- control.should_receive(:wait_until_exists!).with(*location)
121
+ expect(control).to receive(:wait_until_exists!).with(*location)
118
122
  end
119
-
123
+
120
124
  def expect_wait_until_not_exists(location)
121
- control.should_receive(:wait_until_not_exists).with(location)
125
+ expect(control).to receive(:wait_until_not_exists).with(location)
122
126
  end
123
127
 
124
128
  def expect_wait_until_not_exists!(location, action)
125
- control.should_receive(:wait_until_not_exists!).with(location)
129
+ expect(control).to receive(:wait_until_not_exists!).with(location)
126
130
  end
127
-
131
+
128
132
  def expect_until_not_exists!(element)
129
- control.should_receive(:until_not_exists!).with(element).and_yield
130
- end
133
+ expect(control).to receive(:until_not_exists!).with(element).and_yield
134
+ end
131
135
  end
132
- end
136
+ end
data/lib/osaka/pages.rb CHANGED
@@ -1,9 +1,9 @@
1
1
 
2
2
  module Osaka
3
-
3
+
4
4
  class PagesError < RuntimeError
5
5
  end
6
-
6
+
7
7
  class PagesMailMergeDialog
8
8
  attr_accessor :control, :location
9
9
 
@@ -11,30 +11,30 @@ module Osaka
11
11
  @location = location
12
12
  @control = control
13
13
  end
14
-
14
+
15
15
  def merge
16
16
  control.click!(at.button("Merge").sheet(1))
17
17
  print_dialog_location = at.window("Print")
18
18
  control.wait_until_exists!(at.menu_button("PDF") + print_dialog_location)
19
19
  TypicalPrintDialog.new(control.name, print_dialog_location)
20
20
  end
21
-
21
+
22
22
  def set_merge_to_new_document
23
23
  set_merge_to_document_printer(1)
24
24
  end
25
-
25
+
26
26
  def set_merge_to_printer
27
27
  set_merge_to_document_printer(2)
28
28
  end
29
-
29
+
30
30
  private
31
31
  def set_merge_to_document_printer(value)
32
32
  control.click(at.pop_up_button(2).sheet(1))
33
33
  control.wait_until_exists!(at.menu_item(value).menu(1).pop_up_button(2).sheet(1))
34
34
  control.click!(at.menu_item(value).menu(1).pop_up_button(2).sheet(1))
35
- end
35
+ end
36
36
  end
37
-
37
+
38
38
  class PagesInspector
39
39
  attr_accessor :control
40
40
  attr_accessor :location_symbol_map
@@ -52,41 +52,50 @@ module Osaka
52
52
  @location_symbol_map[:chart] = 8
53
53
  @location_symbol_map[:link] = 9
54
54
  @location_symbol_map[:quicktime] = 10
55
- end
56
-
55
+ end
56
+
57
57
  def get_location_from_symbol(inspector_name)
58
58
  at.radio_button(@location_symbol_map[inspector_name]).radio_group(1)
59
59
  end
60
-
60
+
61
61
  def select_inspector(inspector)
62
62
  control.click(get_location_from_symbol(inspector))
63
63
  control.wait_until_exists(at.window(inspector.to_s))
64
64
  control.set_current_window(inspector.to_s)
65
65
  end
66
-
66
+
67
67
  def change_mail_merge_source
68
68
  select_inspector(:link)
69
69
  control.click(at.radio_button(3).tab_group(1).group(1)).wait_until_exists(at.button("Choose...").tab_group(1).group(1))
70
- control.click(at.button("Choose...").tab_group(1).group(1))
70
+ control.click(at.button("Choose...").tab_group(1).group(1))
71
71
  end
72
-
72
+
73
73
  end
74
74
 
75
75
  class Pages < TypicalApplication
76
-
76
+
77
77
  def initialize
78
78
  super "Pages"
79
79
  end
80
-
80
+
81
81
  def type(text)
82
82
  control.keystroke(text)
83
83
  end
84
-
84
+
85
85
  def self.create_document(filename, &block)
86
- numbers = Osaka::Pages.new
87
- numbers.create_document(filename, &block)
86
+ pages = Osaka::Pages.new
87
+ pages.create_document(filename, &block)
88
+ end
89
+
90
+ def new_document
91
+ super
92
+ if control.current_window_name == "Template Chooser"
93
+ control.set_current_window(do_and_wait_for_new_window {
94
+ control.click(at.button("Choose").window("Template Chooser"))
95
+ })
96
+ end
88
97
  end
89
-
98
+
90
99
  def set_mail_merge_document(filename)
91
100
  inspector.change_mail_merge_source
92
101
  control.wait_until_exists(at.sheet(1))
@@ -97,19 +106,19 @@ module Osaka
97
106
  if (control.exists?(at.sheet(1).sheet(1)))
98
107
  raise(PagesError, "Setting Mail Merge numbers file failed")
99
108
  end
100
- control.click(at.button("OK").sheet(1))
109
+ control.click(at.button("OK").sheet(1))
101
110
  end
102
-
111
+
103
112
  def mail_merge_field(field_name)
104
113
  control.click_menu_bar(at.menu_item(field_name).menu(1).menu_item("Merge Field"), "Insert")
105
114
  end
106
-
115
+
107
116
  def mail_merge
108
117
  control.click_menu_bar(at.menu_item(20), "Edit")
109
118
  control.wait_until_exists(at.button("Merge").sheet(1))
110
119
  PagesMailMergeDialog.new(at.sheet(1), control)
111
120
  end
112
-
121
+
113
122
  def mail_merge_to_pdf(filename)
114
123
  mail_merge_dialog = mail_merge
115
124
  mail_merge_dialog.set_merge_to_printer
@@ -128,6 +137,6 @@ module Osaka
128
137
  }
129
138
  PagesInspector.new(control.name, at.window(window_name))
130
139
  end
131
-
140
+
132
141
  end
133
- end
142
+ end