diff --git a/.gitignore b/.gitignore index 7e396fd..cb9a328 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ osaka.tmproj osaka*.gem Gemfile.lock +.DS_Store +*.sublime* diff --git a/lib/osaka.rb b/lib/osaka.rb index bbdadbb..115815e 100644 --- a/lib/osaka.rb +++ b/lib/osaka.rb @@ -13,6 +13,8 @@ require 'osaka/typicalopendialog' require 'osaka/typicalsavedialog' require 'osaka/typicalprintdialog' +require 'osaka/typicalfinddialog' +require 'osaka/keynoteprintdialog.rb' #Specific application require 'osaka/pages' diff --git a/lib/osaka/defaultssystem.rb b/lib/osaka/defaultssystem.rb index 09b205b..79d8b23 100644 --- a/lib/osaka/defaultssystem.rb +++ b/lib/osaka/defaultssystem.rb @@ -9,7 +9,7 @@ def initialize(domain) parse_settings_file(Osaka::CommandRunner.run("defaults read #{domain}")) end - def parse_settings_file (settings_from_defaults) + def parse_settings_file(settings_from_defaults) scanner = StringScanner.new (settings_from_defaults) scanner.scan(/{\n/) while scanner.scan(/\s+(.*) = (.*);\n/) do diff --git a/lib/osaka/keynote.rb b/lib/osaka/keynote.rb index be0c088..0ad59ba 100644 --- a/lib/osaka/keynote.rb +++ b/lib/osaka/keynote.rb @@ -1,10 +1,6 @@ module Osaka - class KeynotePrintDialog < TypicalPrintDialog - - end - class Keynote < TypicalApplication def initialize @@ -12,7 +8,7 @@ def initialize end def create_print_dialog(location) - KeynotePrintDialog.new(control.name, at.window("Print")) + Osaka::KeynotePrintDialog.new(control.name, at.window("Print")) end def select_all_slides @@ -20,10 +16,58 @@ def select_all_slides select_all end + def open (filename) + abolutePathFileName = File.absolute_path(filename) + new_window = do_and_wait_for_new_window { + # Weird that keynote v6 open via osascript is flakey + # was: control.tell("open \"#{abolutePathFileName}\"") + # But now uses the run_command + control.run_command "open #{abolutePathFileName}" + } + control.wait_until_exists(at.window(File.basename(filename))) + control.set_current_window(new_window) + end + def light_table_view if control.exists?(at.menu_item("Light Table").menu(1).menu_bar_item("View").menu_bar(1)) control.click(at.menu_item("Light Table").menu(1).menu_bar_item("View").menu_bar(1)) end end + + def click_view_menu item + control.click view_menu_bar_item item + end + + def view_menu_bar_item(item) + at.menu_item(item).menu(1).menu_bar_item("View").menu_bar(1) + end + + def edit_master_slides + click_view_menu "Edit Master Slides" + end + + def exit_master_slides + click_view_menu "Exit Master Slides" + end + + def exit_master_slides + click_view_menu "Exit Master Slides" + end + + def open_print_dialog + control.keystroke("p", :command) + location = at.sheet(1) + control.wait_until_exists(location) + create_dialog(KeynotePrintDialog, location) + end + + def print_pdf output_pdf, slides_per_page + dialog = open_print_dialog + dialog.use_page_margins + dialog.slides_per_page slides_per_page + # dialog.save_as_pdf output_pdf + end + + end end diff --git a/lib/osaka/keynoteflow.rb b/lib/osaka/keynoteflow.rb index 688f6cb..785bcfa 100644 --- a/lib/osaka/keynoteflow.rb +++ b/lib/osaka/keynoteflow.rb @@ -4,11 +4,12 @@ module CommonFlows def self.keynote_combine_files(result_file, files_to_merge) keynote = Osaka::Keynote.new keynote.activate + keynote.close_template_chooser_if_any keynote.raise_error_on_open_standard_windows("All Keynote windows must be closed before running this flow") files_to_merge = [files_to_merge].flatten keynote.open(files_to_merge.shift) - keynote.light_table_view + keynote.select_all_slides keynote.save_as(result_file) @@ -17,12 +18,12 @@ def self.keynote_combine_files(result_file, files_to_merge) combine_keynote.open(file) combine_keynote.select_all_slides combine_keynote.copy - combine_keynote.close - keynote.select_all_slides keynote.paste + combine_keynote.close + keynote.save + puts "Finished " + file } - keynote.save keynote.close keynote.quit end @@ -33,5 +34,50 @@ def self.keynote_combine_files_from_directory_sorted(result_file, directory = ". files_to_open = files_in_directory.collect { |f| File.join(directory, f)} keynote_combine_files(result_file, files_to_open.sort) end - + + def self.keynote_yield_for_each_file(files) + keynote = Osaka::Keynote.new + keynote.activate + keynote.close_template_chooser_if_any + keynote.raise_error_on_open_standard_windows("All Keynote windows must be closed before running this flow") + files = [files].flatten + files.each { |file| + keynote = Osaka::Keynote.new + keynote.open(file) + yield keynote + keynote.close + } + keynote.quit + end + + def self.keynote_combine_files_from_list(result_file, directory, keynote_files) + files_with_path = keynote_files.collect { |f| File.join(directory, f)} + missing_files = "" + files_with_path.each { |f| + if !File.exist?(f) + missing_files += "\n" + f + end + } + + if missing_files.empty? + keynote_combine_files(result_file, files_with_path) + else + puts "These files do not exist: " + missing_files + end + + end + + def self.start_keynote + keynote = Osaka::Keynote.new + keynote.activate + keynote.close_template_chooser_if_any + keynote.raise_error_on_open_standard_windows("All Keynote windows must be closed before running this flow") + keynote + end + + def self.search_and_replace_presentation_text(keynote, find, replacement) + keynote.find_replace_all(find, replacement) + keynote.save + end + end diff --git a/lib/osaka/keynoteprintdialog.rb b/lib/osaka/keynoteprintdialog.rb new file mode 100644 index 0000000..e5f7b28 --- /dev/null +++ b/lib/osaka/keynoteprintdialog.rb @@ -0,0 +1,48 @@ +module Osaka + + class KeynotePrintDialog < TypicalPrintDialog + attr_accessor :control + + def initialize(application_name, own_location) + @control = Osaka::RemoteControl.new(application_name, own_location) + end + + def margins(value) + element = at.checkbox("Use page margins").group(3) + control.set_checkbox(element, value) + end + + def backgrounds(value) + element = at.checkbox("Print slide backgrounds") + control.set_checkbox(element, value) + end + + def animations(value) + element = at.checkbox("Print each stage of builds") + control.set_checkbox(element, value) + end + + def save_pdf_course_notes(filename = nil) + open_save_as_pdf_dialog + if filename + control.set("value", at.text_field(1).sheet(1) , filename) + sleep 1 + end + save_pdf + end + + def open_save_as_pdf_dialog + control.keystroke("d", :command) + sleep 1 + end + + def save_pdf + control.click(at.button("Save").sheet(1)) + end + + def cancel + control.click(at.button("Cancel")) + end + end +end + diff --git a/lib/osaka/location.rb b/lib/osaka/location.rb index 491986d..2e7444b 100644 --- a/lib/osaka/location.rb +++ b/lib/osaka/location.rb @@ -74,6 +74,10 @@ def menu_bar(name) create_location_with_added_name("menu bar", name) end + def combo_box(name) + create_location_with_added_name("combo box", name) + end + def has_menu_bar? has_element?("menu bar") end @@ -86,6 +90,10 @@ def dialog(name) create_location_with_added_name("dialog", name) end + def floating_window(name) + create_location_with_added_name("floating window", name) + end + def checkbox(name) create_location_with_added_name("checkbox", name) end diff --git a/lib/osaka/remotecontrol.rb b/lib/osaka/remotecontrol.rb index 76f3d2a..3ca130c 100644 --- a/lib/osaka/remotecontrol.rb +++ b/lib/osaka/remotecontrol.rb @@ -1,4 +1,4 @@ - + require 'timeout' module Osaka @@ -149,7 +149,15 @@ def click_menu_bar(menu_item, menu_name) menu_bar_location = at.menu_bar_item(menu_name).menu_bar(1) click!(menu_item + at.menu(1) + menu_bar_location) end - + + def set_checkbox(element, value) + its_value = get!("value", element).to_i + value = value ? 1 : 0 + return if its_value == value + click(element) + sleep 1 + end + def set!(element, location, value) encoded_value = (value.class == String) ? "\"#{value}\"" : value.to_s check_output( system_event!("set #{element}#{construct_prefixed_location(location)} to #{encoded_value}"), "set") @@ -252,9 +260,8 @@ def mac_version_string @mac_version_string end - - def convert_mac_version_string_to_symbol(version_string) - + def run_command command + Osaka::CommandRunner.run command end end diff --git a/lib/osaka/typicalapplication.rb b/lib/osaka/typicalapplication.rb index 078bdf5..1a4e6d0 100644 --- a/lib/osaka/typicalapplication.rb +++ b/lib/osaka/typicalapplication.rb @@ -32,7 +32,7 @@ def get_info ApplicationInfo.new(script_info) end - def open (filename) + def open(filename) abolutePathFileName = File.absolute_path(filename) new_window = do_and_wait_for_new_window { control.tell("open \"#{abolutePathFileName}\"") @@ -122,7 +122,15 @@ def duplicate_and_close_original def save control.keystroke("s", :command) end - + + def find_replace_all text, replacement + control.keystroke("f", :command) + location = at.window("Find & Replace") + control.wait_until_exists(location) + dialog = create_dialog(TypicalFindDialog, location) + dialog.find_replace_all text, replacement + end + def save_pops_up_dialog? control.exists?(at.menu_item("Save…").menu(1).menu_bar_item("File").menu_bar(1)) end @@ -185,9 +193,9 @@ def select_all control.keystroke("a", :command) end - def print_dialog + def print_dialog dialog_class = TypicalPrintDialog control.keystroke("p", :command).wait_until_exists(at.sheet(1)) - create_dialog(TypicalPrintDialog, at.sheet(1)) + create_dialog(dialog_class, at.sheet(1)) end def create_dialog(dialog_class, location) @@ -200,8 +208,25 @@ def select_file_from_open_dialog(filename, dialog_location) dialog.select_file(File.basename(filename)) end + def template_chooser_window? + focus + current_window_name = control.current_window_name + current_window_name == "Choose a Theme" || + current_window_name == "Choose a Template" || + current_window_name == "Template Chooser" ? true : false + end + + def close_template_chooser_if_any + if template_chooser_window? + window = at.window(control.current_window_name) + close + control.wait_until_not_exists!(window) + end + end + def raise_error_on_open_standard_windows(error_message) raise Osaka::ApplicationWindowsMustBeClosed, error_message if ! control.standard_window_list.empty? end end end + diff --git a/lib/osaka/typicalfinddialog.rb b/lib/osaka/typicalfinddialog.rb new file mode 100644 index 0000000..bf15f11 --- /dev/null +++ b/lib/osaka/typicalfinddialog.rb @@ -0,0 +1,40 @@ +# encoding: utf-8 +module Osaka + + class TypicalFindDialog + + def initialize(application_name, own_location) + @control = Osaka::RemoteControl.new(application_name, own_location) + end + + def find_replace_all string, replacement + string_to_find string + string_replacement replacement + wait_for_replace_all_button? + click_replace_all + close + end + + def string_to_find string + @control.set("value", at.text_field(1), string) + end + + def string_replacement replacement + @control.set("value", at.text_field(2) , replacement) + end + + def wait_for_replace_all_button? + @control.wait_until_exists(at.button("Replace All")) + end + + def click_replace_all + @control.click(at.button("Replace All")) + end + + def close + @control.keystroke('w', :command) + end + + end + +end diff --git a/lib/osaka/typicalfinderdialog.rb b/lib/osaka/typicalfinderdialog.rb index b2ea52c..04dee0c 100644 --- a/lib/osaka/typicalfinderdialog.rb +++ b/lib/osaka/typicalfinderdialog.rb @@ -11,7 +11,8 @@ def initialize(application_name, own_location) def set_folder(pathname) return if pathname == "." control.keystroke("g", [ :command, :shift ]).wait_until_exists(at.sheet(1)) - control.set("value", at.text_field(1).sheet(1), pathname) + # pre mojave control.set("value", at.text_field(1).sheet(1), pathname) + control.set("value", at.combo_box(1).sheet(1), pathname) sleep(1) # Seems this must be here due to the sucking Apple UI. Not found something else to wait for! control.click(at.button("Go").sheet(1)).wait_until_not_exists(at.sheet(1)) end diff --git a/make-gem.sh b/make-gem.sh new file mode 100755 index 0000000..091a93d --- /dev/null +++ b/make-gem.sh @@ -0,0 +1,4 @@ +#/bin/bash +gem build osaka.gemfile +gem install osaka-0.42.0.gem + diff --git a/osaka.gemspec b/osaka.gemfile similarity index 54% rename from osaka.gemspec rename to osaka.gemfile index 4ea7b2e..35f5ca8 100644 --- a/osaka.gemspec +++ b/osaka.gemfile @@ -1,9 +1,12 @@ # encoding: utf-8 +puts "File", __FILE__ +puts File.expand_path('../lib/osaka/version', __FILE__) require File.expand_path('../lib/osaka/version', __FILE__) +require 'Date' Gem::Specification.new do |gem| gem.name = 'osaka' - gem.version = Osaka::VERSION + gem.version = '0.42.0' #Osaka::VERSION gem.date = Date.today.to_s gem.summary = "Osaka is an Mac GUI automation library" @@ -13,8 +16,12 @@ Gem::Specification.new do |gem| gem.email = 'basv@odd-e.com' gem.homepage = 'https://github.com/basvodde/osaka' - gem.add_dependency('rake') - gem.add_development_dependency('rspec', [">= 2.0.0"]) + gem.add_dependency('rake', ["~>12"]) + gem.add_development_dependency('rspec', ["~> 2.0"]) + gem.license = 'MIT' - gem.files = `git ls-files -- {.,test,spec,lib}/*`.split("\n") + + gem.files = `git ls-files -- {lib,lib/osaka,spec}/*.rb`.split("\n") + puts gem.files +# gem.files = `git ls-files -- {.,test,spec,lib}/*`.split("\n") end diff --git a/run_each_test.sh b/run_each_test.sh new file mode 100755 index 0000000..71c4aad --- /dev/null +++ b/run_each_test.sh @@ -0,0 +1,43 @@ +UNIT_TESTS+=" ./spec/calculator_spec.rb" +UNIT_TESTS+=" ./spec/defaultssystem_spec.rb" +UNIT_TESTS+=" ./spec/keynote_flows_spec.rb" +UNIT_TESTS+=" ./spec/keynote_spec.rb" +UNIT_TESTS+=" ./spec/launchservices_spec.rb" +UNIT_TESTS+=" ./spec/location_spec.rb" +UNIT_TESTS+=" ./spec/mailmergeflow_spec.rb" +UNIT_TESTS+=" ./spec/numbers_spec.rb" +UNIT_TESTS+=" ./spec/osakaexpectations_spec.rb" +UNIT_TESTS+=" ./spec/pages_spec.rb" +UNIT_TESTS+=" ./spec/preview_spec.rb" +UNIT_TESTS+=" ./spec/remotecontrol_spec.rb" +UNIT_TESTS+=" ./spec/scriptrunner_spec.rb" +UNIT_TESTS+=" ./spec/textedit_spec.rb" +UNIT_TESTS+=" ./spec/typicalapplication_spec.rb" +UNIT_TESTS+=" ./spec/typicalfinderdialog_spec.rb" +UNIT_TESTS+=" ./spec/typicalopendialog_spec.rb" +UNIT_TESTS+=" ./spec/typicalprintdialog_spec.rb" +UNIT_TESTS+=" ./spec/keynoteprintdialog_spec.rb" +UNIT_TESTS+=" ./spec/typicalsavedialog_spec.rb" +UNIT_TESTS+=" ./spec/typicalfinddialog_spec.rb" + +# INTEGRATION_TESTS+=" ./spec/integration_calculator_spec.rb" +INTEGRATION_TESTS+=" ./spec/integration_keynote_spec.rb" +# INTEGRATION_TESTS+=" ./spec/keynoteprintdialog_spec.rb" +# INTEGRATION_TESTS+=" ./spec/integration_numbers_spec.rb" +# INTEGRATION_TESTS+=" ./spec/integration_textedit_spec.rb" + +## INTEGRATION_TESTS+=" ./spec/integration_preview_spec.rb" +## INTEGRATION_TESTS+=" ./spec/integration_pages_numbers_mail_merge_spec.rb" + +export LANG=en_US.UTF-8 + +ruby -S rspec $UNIT_TESTS + +if [ "$1" == "i" ] ; then + ruby -S rspec $INTEGRATION_TESTS +fi + +# git commit . -m "Convert expect 's/$n.should_receive/expect($n).to receive/' for n=Osaka::CommandRunner" +# find . -name "*.rb" | xargs sed -e"s/$n.should_receive/expect($n).to receive/" -i '' + + diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/Girl_and_Snowcone-small-97.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/Girl_and_Snowcone-small-97.jpg new file mode 100644 index 0000000..49cd917 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/Girl_and_Snowcone-small-97.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/Happy_Girls-small-95.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/Happy_Girls-small-95.jpg new file mode 100644 index 0000000..23ff195 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/Happy_Girls-small-95.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt0@2x-130.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt0@2x-130.jpg new file mode 100644 index 0000000..ba92f21 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt0@2x-130.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt10@2x-109.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt10@2x-109.jpg new file mode 100644 index 0000000..133f299 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt10@2x-109.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt11@2x-110.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt11@2x-110.jpg new file mode 100644 index 0000000..11cd202 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt11@2x-110.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt12@2x-111.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt12@2x-111.jpg new file mode 100644 index 0000000..254a2d3 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt12@2x-111.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt13@2x-112.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt13@2x-112.jpg new file mode 100644 index 0000000..5387972 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt13@2x-112.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt1@2x-132.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt1@2x-132.jpg new file mode 100644 index 0000000..7071946 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt1@2x-132.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt2@2x-133.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt2@2x-133.jpg new file mode 100644 index 0000000..3a5911c Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt2@2x-133.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt3@2x-102.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt3@2x-102.jpg new file mode 100644 index 0000000..08b96be Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt3@2x-102.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt4@2x-103.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt4@2x-103.jpg new file mode 100644 index 0000000..8c8cafc Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt4@2x-103.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt5@2x-104.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt5@2x-104.jpg new file mode 100644 index 0000000..42694af Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt5@2x-104.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt6@2x-105.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt6@2x-105.jpg new file mode 100644 index 0000000..25ecd11 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt6@2x-105.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt7@2x-106.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt7@2x-106.jpg new file mode 100644 index 0000000..68d01bd Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt7@2x-106.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt8@2x-107.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt8@2x-107.jpg new file mode 100644 index 0000000..1a1ad1b Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt8@2x-107.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/mt9@2x-108.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt9@2x-108.jpg new file mode 100644 index 0000000..9e529bd Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/mt9@2x-108.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/st1-198.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/st1-198.jpg new file mode 100644 index 0000000..564badb Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/st1-198.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Data/st2-199.jpg b/spec/assets/keynote-6/slides_with_master_text.key/Data/st2-199.jpg new file mode 100644 index 0000000..6620be6 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Data/st2-199.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Index.zip b/spec/assets/keynote-6/slides_with_master_text.key/Index.zip new file mode 100644 index 0000000..2a60627 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Index.zip differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Metadata/BuildVersionHistory.plist b/spec/assets/keynote-6/slides_with_master_text.key/Metadata/BuildVersionHistory.plist new file mode 100644 index 0000000..21f2269 --- /dev/null +++ b/spec/assets/keynote-6/slides_with_master_text.key/Metadata/BuildVersionHistory.plist @@ -0,0 +1,9 @@ + + + + + local build-Nov 15 2011 + local build-Jun 29 2012 + M6.2.2-1878-1 + + diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Metadata/DocumentIdentifier b/spec/assets/keynote-6/slides_with_master_text.key/Metadata/DocumentIdentifier new file mode 100644 index 0000000..d45eb59 --- /dev/null +++ b/spec/assets/keynote-6/slides_with_master_text.key/Metadata/DocumentIdentifier @@ -0,0 +1 @@ +028F036E-BD94-4E84-BE38-762C1ED99D3A \ No newline at end of file diff --git a/spec/assets/keynote-6/slides_with_master_text.key/Metadata/Properties.plist b/spec/assets/keynote-6/slides_with_master_text.key/Metadata/Properties.plist new file mode 100644 index 0000000..8605149 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/Metadata/Properties.plist differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/preview-micro.jpg b/spec/assets/keynote-6/slides_with_master_text.key/preview-micro.jpg new file mode 100644 index 0000000..e515956 Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/preview-micro.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/preview-web.jpg b/spec/assets/keynote-6/slides_with_master_text.key/preview-web.jpg new file mode 100644 index 0000000..f410a9e Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/preview-web.jpg differ diff --git a/spec/assets/keynote-6/slides_with_master_text.key/preview.jpg b/spec/assets/keynote-6/slides_with_master_text.key/preview.jpg new file mode 100644 index 0000000..9ea4beb Binary files /dev/null and b/spec/assets/keynote-6/slides_with_master_text.key/preview.jpg differ diff --git a/spec/integration_keynote_spec.rb b/spec/integration_keynote_spec.rb index 6d38e09..3cfb3aa 100644 --- a/spec/integration_keynote_spec.rb +++ b/spec/integration_keynote_spec.rb @@ -4,39 +4,93 @@ describe "Integration tests for Keynote and Common Flows", :integration => true do before(:each) do - @assets_directory = File.join(File.dirname(__FILE__), "assets") + @assets_directory = "spec/assets" end - it "Should be able to do a combine with just one file" do + # it "Should be able to do a combine with just one file" do - keynote_file = File.join(@assets_directory, "01_first_slides.key") - Dir.mktmpdir { |dir| - results_file = File.join(dir, "results.key") - CommonFlows.keynote_combine_files(results_file, keynote_file) - expect(File.exists?(results_file)).to eq true - } - end + # keynote_file = File.join(@assets_directory, "01_first_slides.key") + # Dir.mktmpdir { |dir| + # results_file = File.join(dir, "results.key") + # CommonFlows.keynote_combine_files(results_file, keynote_file) + # expect(File.exists?(results_file)).to eq true + # } + # end - it "Should be able to combine multiple files" do + # it "Should be able to combine multiple files" do - Dir.mktmpdir { |dir| - results_file = File.join(dir, "results.key") - CommonFlows.keynote_combine_files_from_directory_sorted(results_file, @assets_directory) - expect(File.exists?(results_file)).to eq true - } - end + # Dir.mktmpdir { |dir| + # results_file = File.join(dir, "results.key") + # CommonFlows.keynote_combine_files_from_directory_sorted(results_file, @assets_directory) + # expect(File.exists?(results_file)).to eq true + # } + # end - it "Should exit with message if files are open" do - - keynote_file = File.join(@assets_directory, "01_first_slides.key") - keynote = Osaka::Keynote.new - keynote.open(keynote_file) + # it "Should exit with message if files are open" do + + # keynote_file = File.join(@assets_directory, "01_first_slides.key") + # keynote = Osaka::Keynote.new + # keynote.activate + # keynote.close_template_chooser_if_any + # keynote.open(keynote_file) + + # expect { + # CommonFlows.keynote_combine_files(nil, keynote_file) + # }.to raise_error(Osaka::ApplicationWindowsMustBeClosed, "All Keynote windows must be closed before running this flow") + + # keynote.close + # end + + # it "Should be able to combine multiple files from a file list" do - expect { - CommonFlows.keynote_combine_files(nil, keynote_file) - }.to raise_error(Osaka::ApplicationWindowsMustBeClosed, "All Keynote windows must be closed before running this flow") + # Dir.mktmpdir { |dir| + # results_file = File.join(dir, "results.key") + # CommonFlows.keynote_combine_files_from_list(results_file, @assets_directory, ["01_first_slides.key", "02_second_slides.key", "03_third_slides.key"]) + # expect(File.exists?(results_file)).to be(true) + # } + # end + # it "Should be complain when files in list do not exist" do + + # Dir.mktmpdir { |dir| + # results_file = File.join(dir, "results.key") + # expect(STDOUT).to receive(:puts).exactly(1).times + # CommonFlows.keynote_combine_files_from_list(results_file, @assets_directory, ["a.key", "b.key"]) + # expect(File.exists?(results_file)).to be(false) + # } + # end + + # it "Should find and replace text" do + # input_file = File.join(@assets_directory + "/keynote-6", "slides_with_master_text.key") + # results_file = File.join(Dir.mktmpdir, "results.key") + # keynote = CommonFlows.start_keynote + # keynote.open input_file + # keynote.save_as results_file + # CommonFlows.search_and_replace_presentation_text(keynote, "__TITLE__", "This is it!") + # keynote.close + # end + + # it "Should find and replace text in master slides" do + # input_file = File.join(@assets_directory + "/keynote-6", "slides_with_master_text.key") + # results_file = File.join(Dir.mktmpdir, "results.key") + # keynote = CommonFlows.start_keynote + # keynote.open input_file + # keynote.save_as results_file + # keynote.edit_master_slides + # CommonFlows.search_and_replace_presentation_text(keynote, "master-slide-text", "custom master slide text") + # keynote.exit_master_slides + # keynote.close + # end + + it "Should save to pdf" do +Osaka::ScriptRunner::enable_debug_prints + input_file = File.join(@assets_directory + "/keynote-6", "slides_with_master_text.key") + pdf_file = File.join(Dir.mktmpdir, "output.key.pdf") + keynote = CommonFlows.start_keynote + keynote.open input_file + keynote.print_pdf pdf_file, 4 keynote.close end - + + end diff --git a/spec/keynote_flows_spec.rb b/spec/keynote_flows_spec.rb index 280f7e7..f78612f 100644 --- a/spec/keynote_flows_spec.rb +++ b/spec/keynote_flows_spec.rb @@ -3,8 +3,36 @@ describe "Common flows in keynote" do - def should_shutdown + let(:mock_keynote) { double("First keynote")} + + def should_get_new_keynote_then_return_mock mock = mock_keynote + expect(Osaka::Keynote).to receive(:new).and_return(mock) + end + + def should_get_started + expect(mock_keynote).to receive(:activate) + expect(mock_keynote).to receive(:close_template_chooser_if_any) + expect(mock_keynote).to receive(:raise_error_on_open_standard_windows) + end + + def should_create_output_file_from_input(input_file, result_file) + expect(mock_keynote).to receive(:open).with(input_file) + expect(mock_keynote).to receive(:select_all_slides) + expect(mock_keynote).to receive(:save_as).with(result_file) + end + + def should_append_file(file) + another_keynote = double("keynote with " + file) + should_get_new_keynote_then_return_mock another_keynote + expect(another_keynote).to receive(:open).with(file) + expect(another_keynote).to receive(:select_all_slides) + expect(another_keynote).to receive(:copy) + expect(mock_keynote).to receive(:paste) + expect(another_keynote).to receive(:close) expect(mock_keynote).to receive(:save) + end + + def should_shutdown expect(mock_keynote).to receive(:close) expect(mock_keynote).to receive(:quit) end @@ -12,9 +40,8 @@ def should_shutdown let(:mock_keynote) { double("First keynote")} it "Should exit if keynote windows are already open" do - expect(Osaka::Keynote).to receive(:new).and_return(mock_keynote) - expect(mock_keynote).to receive(:activate) - expect(mock_keynote).to receive(:raise_error_on_open_standard_windows) + should_get_new_keynote_then_return_mock + should_get_started .with("All Keynote windows must be closed before running this flow") .and_raise(Osaka::ApplicationWindowsMustBeClosed, "All Keynote windows must be closed before running this flow") @@ -24,38 +51,19 @@ def should_shutdown end it "Should be able to combine just one single file" do - expect(Osaka::Keynote).to receive(:new).and_return(mock_keynote) - expect(mock_keynote).to receive(:activate) - expect(mock_keynote).to receive(:raise_error_on_open_standard_windows) - expect(mock_keynote).to receive(:light_table_view) - expect(mock_keynote).to receive(:open).with("one_file.key") - expect(mock_keynote).to receive(:save_as).with("result.key") + should_get_new_keynote_then_return_mock + should_get_started + should_create_output_file_from_input("one_file.key", "result.key") should_shutdown CommonFlows.keynote_combine_files("result.key", "one_file.key") end it "Should be able to combine multiple files in one result" do - mock2_keynote = double("Second keynote") - mock3_keynote = double("Third keynote") - expect(Osaka::Keynote).to receive(:new).and_return(mock_keynote, mock2_keynote, mock3_keynote) - expect(mock_keynote).to receive(:activate) - expect(mock_keynote).to receive(:raise_error_on_open_standard_windows) - expect(mock_keynote).to receive(:open).with("one_file.key") - expect(mock_keynote).to receive(:light_table_view) - expect(mock_keynote).to receive(:save_as).with("result.key") - expect(mock_keynote).to receive(:select_all_slides).exactly(2).times - expect(mock_keynote).to receive(:paste).exactly(2).times - - expect(mock2_keynote).to receive(:open).with("two_file.key") - expect(mock2_keynote).to receive(:select_all_slides) - expect(mock2_keynote).to receive(:copy) - expect(mock2_keynote).to receive(:close) - - expect(mock3_keynote).to receive(:open).with("three_file.key") - expect(mock3_keynote).to receive(:select_all_slides) - expect(mock3_keynote).to receive(:copy) - expect(mock3_keynote).to receive(:close) - + should_get_new_keynote_then_return_mock + should_get_started + should_create_output_file_from_input("one_file.key", "result.key") + should_append_file("two_file.key") + should_append_file("three_file.key") should_shutdown CommonFlows.keynote_combine_files("result.key", ["one_file.key", "two_file.key", "three_file.key"]) end @@ -77,5 +85,35 @@ def should_shutdown expect(CommonFlows).to receive(:keynote_combine_files).with("results.key", files_in_dir_to_be_used) CommonFlows.keynote_combine_files_from_directory_sorted("results.key", "dirname", /^\d+.*\.key$/) end + + it "Should be able to open and close keynote files" do + expect(Osaka::Keynote).to receive(:new).exactly(3).times.and_return(mock_keynote) + should_get_started + expect(mock_keynote).to receive(:open).with("file1.key") + expect(mock_keynote).to receive(:close) + expect(mock_keynote).to receive(:open).with("file2.key") + expect(mock_keynote).to receive(:close) + expect(mock_keynote).to receive(:quit) + CommonFlows.keynote_yield_for_each_file(["file1.key", "file2.key"]) { |k| k.instance_of? Osaka::Keynote } + end + + it "Should be able to combine a list of files fron a specified directory" do + expect(File).to receive(:exist?).exactly(2).times.and_return(false) + expect(STDOUT).to receive(:puts).exactly(1).times.with("These files do not exist: \ndir/file1.key\ndir/file2.key") + CommonFlows.keynote_combine_files_from_list("results_file", "dir", ["file1.key", "file2.key"]) + end + + it "Should be complain when files in list do not exist" do + expect(File).to receive(:exist?).exactly(2).times.and_return(true) + expect(CommonFlows).to receive(:keynote_combine_files).with("results_file", ["dir/file1.key", "dir/file2.key"]) + CommonFlows.keynote_combine_files_from_list("results_file", "dir", ["file1.key", "file2.key"]) + end + + it "Should be able to search and replace presentation text in a file" do + expect(mock_keynote).to receive(:find_replace_all).with("11111", "22222") + expect(mock_keynote).to receive(:save) + CommonFlows.search_and_replace_presentation_text(mock_keynote, "11111", "22222") + end + end diff --git a/spec/keynote_spec.rb b/spec/keynote_spec.rb index ac56b69..5a4b138 100644 --- a/spec/keynote_spec.rb +++ b/spec/keynote_spec.rb @@ -7,7 +7,8 @@ subject { Osaka::Keynote.new } let(:control) {subject.control = double("RemoteControl")} - + let(:print_dialog) { double("KeynotePrintDialog") } + it "Should create the correct keynote print dialog" do expect(subject.create_print_dialog("window")).to be_instance_of Osaka::KeynotePrintDialog end @@ -39,5 +40,22 @@ expect(subject).to receive(:select_all) subject.select_all_slides end - + + it "Should use the command line open to make up for problem in keynote 6.2" do + expect(File).to receive(:absolute_path).with("file.key").and_return("/path/file.key") + expect(subject).to receive(:do_and_wait_for_new_window).and_yield.and_return("new_window") + expect(subject.control).to receive(:run_command).with("open /path/file.key").and_return("something that is printed during debug") + expect(subject.control).to receive(:wait_until_exists) + expect(subject.control).to receive(:set_current_window).with("new_window") + subject.open("file.key") + end + + it "should be able to edit and exit the master slides" do + expect(subject).to receive(:click_view_menu).with "Edit Master Slides" + expect(subject).to receive(:click_view_menu).with "Exit Master Slides" + subject.edit_master_slides + subject.exit_master_slides + end + + end diff --git a/spec/keynoteprintdialog_spec.rb b/spec/keynoteprintdialog_spec.rb new file mode 100644 index 0000000..6666a26 --- /dev/null +++ b/spec/keynoteprintdialog_spec.rb @@ -0,0 +1,42 @@ +# encoding: utf-8 +require 'osaka' + +describe "Osaka::KeynotePrintDialog" do + + include(*Osaka::OsakaExpectations) + subject { Osaka::KeynotePrintDialog.new("App", at.window("Print")) } + + let(:control) { subject.control = double("RemoteControl", :name => "App") } + margins_checkbox = at.checkbox("Use page margins").group(3) + backgrounds_checkbox = at.checkbox("Print slide backgrounds") + animations_checkbox = at.checkbox("Print each stage of builds") + + def expect_check_box_should_be_set(element) + expect(control).to receive(:set_checkbox).with(element, true) + end + + def expect_check_box_should_be_cleared(element) + expect(control).to receive(:set_checkbox).with(element, false) + end + + it "Should be able to set margins, backgrounds, animations" do + expect_check_box_should_be_set(margins_checkbox) + expect_check_box_should_be_set(backgrounds_checkbox) + expect_check_box_should_be_set(animations_checkbox) + + subject.margins(true) + subject.backgrounds(true) + subject.animations(true) + end + + it "Should be able to clear margins, backgrounds, animations" do + expect_check_box_should_be_cleared(margins_checkbox) + expect_check_box_should_be_cleared(backgrounds_checkbox) + expect_check_box_should_be_cleared(animations_checkbox) + + subject.margins(false) + subject.backgrounds(false) + subject.animations(false) + end + +end diff --git a/spec/remotecontrol_spec.rb b/spec/remotecontrol_spec.rb index b203b3a..cac8d0c 100644 --- a/spec/remotecontrol_spec.rb +++ b/spec/remotecontrol_spec.rb @@ -115,6 +115,13 @@ def expect_execute_and_warning_for(action) expect_system_event!("quit") subject.system_event("quit") end + + it "Should be able to able to run shell commands" do + command_output = "something that is the command output" + expect(Osaka::CommandRunner).to receive(:run).with("open xxx.key").and_return(command_output) + expect(subject.run_command("open xxx.key")).to eq command_output + end + end context "Check whether things exist or not" do @@ -290,7 +297,34 @@ def expect_execute_and_warning_for(action) expect_click!(at.menu_item("Hey").menu(1).menu_bar_item("File").menu_bar(1)) subject.click_menu_bar(at.menu_item("Hey"), "File") end - + + it "Should click a cleared checkbox when true is specified" do + element = "some_element" + expect(control).to receive(:get!).with("value", element).and_return(0) + expect(control).to receive(:click).with(element) + control.set_checkbox(element, true) + end + + it "Should click a set checkbox when false is specified" do + element = "some_element" + expect(control).to receive(:get!).with("value", element).and_return(1) + expect(control).to receive(:click).with(element) + control.set_checkbox(element, false) + end + + it "Should not click a set checkbox when true is specified" do + element = "some_element" + expect(control).to receive(:get!).with("value", element).and_return(1) + control.set_checkbox(element, true) + end + + it "Should not click a cleared checkbox when false is specified" do + element = "some_element" + expect(control).to receive(:get!).with("value", element).and_return(1) + control.set_checkbox(element, true) + end + + end context "Control should be able to set and get different application values" do diff --git a/spec/typicalapplication_spec.rb b/spec/typicalapplication_spec.rb index b5fafd4..1f507dc 100644 --- a/spec/typicalapplication_spec.rb +++ b/spec/typicalapplication_spec.rb @@ -175,7 +175,6 @@ subject.select_file_from_open_dialog("/tmp/filename", at.window("dialog")) end - it "Should be able to duplicate and close the original document" do allow(subject).to receive_message_chain(:duplicate, :control).and_return(new_instance_control) expect(subject).to receive(:close) @@ -308,5 +307,48 @@ subject.raise_error_on_open_standard_windows("error message") }.to raise_error(Osaka::ApplicationWindowsMustBeClosed, "error message") end + + it "Should not close the template chooser if not present" do + expect(subject).to receive(:template_chooser_window?).and_return(false) + subject.close_template_chooser_if_any + end + + it "Should close the template chooser if present" do + template_window = "the window" + expect(subject).to receive(:template_chooser_window?).and_return true + expect(control).to receive(:current_window_name).and_return template_window + expect(subject).to receive(:close) + expect(control).to receive(:wait_until_not_exists!).with(at.window(template_window)) + subject.close_template_chooser_if_any + end + + def valid_template_chooser_window name + expect(subject).to receive(:focus) + expect(control).to receive(:current_window_name).and_return name + expect(subject.template_chooser_window?).to be true + end + + it "Should recognize various template chooser names" do + valid_template_chooser_window "Choose a Theme" + valid_template_chooser_window "Choose a Template" + valid_template_chooser_window "Template Chooser" + end + + context "find and replace" do + let(:find_dialog) { double("TypicalFindDialog") } + let(:new_instance_control) { double("RemoteControl") } + let(:replace_all_button) { double("RemoteControl") } + + it "Should be able to replace all occurrences of a string" do + expect_keystroke("f", :command) + location = at.window("Find & Replace") + expect(control).to receive(:wait_until_exists).with(location).and_return(true) + expect(subject).to receive(:create_dialog).with(Osaka::TypicalFindDialog, location).and_return(find_dialog) + expect(find_dialog).to receive(:find_replace_all).with "some string", "some replacement" + subject.find_replace_all "some string", "some replacement" + end + + end + end diff --git a/spec/typicalfinddialog_spec.rb b/spec/typicalfinddialog_spec.rb new file mode 100644 index 0000000..4959832 --- /dev/null +++ b/spec/typicalfinddialog_spec.rb @@ -0,0 +1,19 @@ +# encoding: utf-8 +require 'osaka' + +describe "Osaka::TypicalFindDialog" do + + include(*Osaka::OsakaExpectations) + subject { Osaka::TypicalFindDialog.new("Application", at.window(1))} + let(:control) { subject.control = double("RemoteControl", :base_location => at.window(1)) } + + it "Should be able to populate the dialog" do + expect(subject).to receive(:string_to_find).with "string" + expect(subject).to receive(:string_replacement).with "replacement" + expect(subject).to receive(:wait_for_replace_all_button?).and_return(true) + expect(subject).to receive(:click_replace_all) + expect(subject).to receive :close + subject.find_replace_all("string", "replacement") + end + +end diff --git a/spec/typicalfinderdialog_spec.rb b/spec/typicalfinderdialog_spec.rb index 51111cd..49a5380 100644 --- a/spec/typicalfinderdialog_spec.rb +++ b/spec/typicalfinderdialog_spec.rb @@ -11,7 +11,7 @@ it "Should be able to set the path" do expect_keystroke("g", [ :command, :shift ]) expect_wait_until_exists(at.sheet(1)) - expect_set("value", at.text_field(1).sheet(1), "path") + expect_set("value", at.combo_box(1).sheet(1), "path") expect_click(at.button("Go").sheet(1)) expect_wait_until_not_exists(at.sheet(1)) subject.set_folder("path")