rb-scrpt 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES +497 -0
- data/README.md +8 -0
- data/Rakefile +32 -0
- data/doc/aem-manual/01_introduction.html +60 -0
- data/doc/aem-manual/02_apioverview.html +107 -0
- data/doc/aem-manual/03_packingandunpackingdata.html +135 -0
- data/doc/aem-manual/04_references.html +409 -0
- data/doc/aem-manual/05_targetingapplications.html +164 -0
- data/doc/aem-manual/06_buildingandsendingevents.html +229 -0
- data/doc/aem-manual/07_findapp.html +63 -0
- data/doc/aem-manual/08_examples.html +94 -0
- data/doc/aem-manual/aemreferenceinheritance.gif +0 -0
- data/doc/aem-manual/index.html +56 -0
- data/doc/appscript-manual/01_introduction.html +94 -0
- data/doc/appscript-manual/02_aboutappscripting.html +247 -0
- data/doc/appscript-manual/03_quicktutorial.html +167 -0
- data/doc/appscript-manual/04_gettinghelp.html +188 -0
- data/doc/appscript-manual/05_keywordconversion.html +106 -0
- data/doc/appscript-manual/06_classesandenums.html +192 -0
- data/doc/appscript-manual/07_applicationobjects.html +211 -0
- data/doc/appscript-manual/08_realvsgenericreferences.html +96 -0
- data/doc/appscript-manual/09_referenceforms.html +241 -0
- data/doc/appscript-manual/10_referenceexamples.html +154 -0
- data/doc/appscript-manual/11_applicationcommands.html +245 -0
- data/doc/appscript-manual/12_commandexamples.html +138 -0
- data/doc/appscript-manual/13_performanceissues.html +142 -0
- data/doc/appscript-manual/14_notes.html +80 -0
- data/doc/appscript-manual/application_architecture.gif +0 -0
- data/doc/appscript-manual/application_architecture2.gif +0 -0
- data/doc/appscript-manual/finder_to_textedit_event.gif +0 -0
- data/doc/appscript-manual/index.html +62 -0
- data/doc/appscript-manual/relationships_example.gif +0 -0
- data/doc/appscript-manual/ruby_to_itunes_event.gif +0 -0
- data/doc/full.css +106 -0
- data/doc/index.html +45 -0
- data/doc/mactypes-manual/01_introduction.html +54 -0
- data/doc/mactypes-manual/02_aliasclass.html +124 -0
- data/doc/mactypes-manual/03_fileurlclass.html +126 -0
- data/doc/mactypes-manual/04_unitsclass.html +100 -0
- data/doc/mactypes-manual/index.html +53 -0
- data/doc/osax-manual/01_introduction.html +67 -0
- data/doc/osax-manual/02_interface.html +147 -0
- data/doc/osax-manual/03_examples.html +73 -0
- data/doc/osax-manual/04_notes.html +61 -0
- data/doc/osax-manual/index.html +53 -0
- data/doc/rb-appscript-logo.png +0 -0
- data/extconf.rb +63 -0
- data/rb-scrpt.gemspec +16 -0
- data/sample/AB_export_vcard.rb +31 -0
- data/sample/AB_list_people_with_emails.rb +13 -0
- data/sample/Add_iCal_event.rb +21 -0
- data/sample/Create_daily_iCal_todos.rb +75 -0
- data/sample/Export_Address_Book_phone_numbers.rb +59 -0
- data/sample/Hello_world.rb +21 -0
- data/sample/List_iTunes_playlist_names.rb +11 -0
- data/sample/Make_Mail_message.rb +33 -0
- data/sample/Open_file_in_TextEdit.rb +13 -0
- data/sample/Organize_Mail_messages.rb +61 -0
- data/sample/Print_folder_tree.rb +16 -0
- data/sample/Select_all_HTML_files.rb +14 -0
- data/sample/Set_iChat_status.rb +24 -0
- data/sample/Simple_Finder_GUI_Scripting.rb +18 -0
- data/sample/Stagger_Finder_windows.rb +25 -0
- data/sample/TextEdit_demo.rb +130 -0
- data/sample/iTunes_top40_to_html.rb +69 -0
- data/src/SendThreadSafe.c +380 -0
- data/src/SendThreadSafe.h +139 -0
- data/src/lib/_aem/aemreference.rb +1021 -0
- data/src/lib/_aem/codecs.rb +661 -0
- data/src/lib/_aem/connect.rb +205 -0
- data/src/lib/_aem/encodingsupport.rb +74 -0
- data/src/lib/_aem/findapp.rb +85 -0
- data/src/lib/_aem/mactypes.rb +250 -0
- data/src/lib/_aem/send.rb +279 -0
- data/src/lib/_aem/typewrappers.rb +59 -0
- data/src/lib/_appscript/defaultterminology.rb +277 -0
- data/src/lib/_appscript/referencerenderer.rb +242 -0
- data/src/lib/_appscript/reservedkeywords.rb +116 -0
- data/src/lib/_appscript/safeobject.rb +250 -0
- data/src/lib/_appscript/terminology.rb +470 -0
- data/src/lib/aem.rb +253 -0
- data/src/lib/kae.rb +1489 -0
- data/src/lib/osax.rb +659 -0
- data/src/lib/rb-scrpt.rb +1073 -0
- data/src/lib/version.rb +3 -0
- data/src/rbae.c +979 -0
- data/test/README +3 -0
- data/test/test_aemreference.rb +115 -0
- data/test/test_appscriptcommands.rb +149 -0
- data/test/test_appscriptreference.rb +103 -0
- data/test/test_codecs.rb +181 -0
- data/test/test_findapp.rb +23 -0
- data/test/test_mactypes.rb +77 -0
- data/test/test_osax.rb +52 -0
- metadata +146 -0
data/test/README
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
Some of the code in these tests may not yet be 100% portable (hardcoded paths, etc) so may currently fail for some users, although they have passed for Ruby 1.8.x on OS X 10.3.9, OS X 10.4.x (PPC & i386) and OS X 10.5.1 (i386).
|
2
|
+
|
3
|
+
Note that some mactypes unit tests may fail as Alias and FileURL comparisons are rather dumb and don't normalise path strings before comparing/hashing. Future releases may try to remedy this.
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require "_aem/aemreference"
|
5
|
+
require "_aem/typewrappers"
|
6
|
+
require "_aem/codecs"
|
7
|
+
|
8
|
+
|
9
|
+
class TC_AEMReferences < Minitest::Test
|
10
|
+
|
11
|
+
def test_reference_forms
|
12
|
+
[
|
13
|
+
[AEMReference::App.property('ctxt'), 'AEM.app.property("ctxt")', nil],
|
14
|
+
|
15
|
+
[AEMReference::App.elements('docu'), 'AEM.app.elements("docu")', nil],
|
16
|
+
|
17
|
+
[AEMReference::App.elements('docu').by_index(1),
|
18
|
+
'AEM.app.elements("docu").by_index(1)', nil],
|
19
|
+
[AEMReference::App.elements('docu').by_name('foo'),
|
20
|
+
'AEM.app.elements("docu").by_name("foo")', nil],
|
21
|
+
[AEMReference::App.elements('docu').by_id(300),
|
22
|
+
'AEM.app.elements("docu").by_id(300)', nil],
|
23
|
+
|
24
|
+
[AEMReference::App.elements('docu').next('docu'),
|
25
|
+
'AEM.app.elements("docu").next("docu")', nil],
|
26
|
+
[AEMReference::App.elements('docu').previous('docu'),
|
27
|
+
'AEM.app.elements("docu").previous("docu")', nil],
|
28
|
+
|
29
|
+
[AEMReference::App.elements('docu').first, 'AEM.app.elements("docu").first', nil],
|
30
|
+
[AEMReference::App.elements('docu').middle, 'AEM.app.elements("docu").middle', nil],
|
31
|
+
[AEMReference::App.elements('docu').last, 'AEM.app.elements("docu").last', nil],
|
32
|
+
[AEMReference::App.elements('docu').any, 'AEM.app.elements("docu").any', nil],
|
33
|
+
|
34
|
+
[AEMReference::Con.elements("docu").by_index(3), 'AEM.con.elements("docu").by_index(3)', nil],
|
35
|
+
|
36
|
+
[AEMReference::App.elements('docu').by_range(
|
37
|
+
AEMReference::Con.elements('docu').by_index(3),
|
38
|
+
AEMReference::Con.elements('docu').by_name('foo')),
|
39
|
+
'AEM.app.elements("docu").by_range(' +
|
40
|
+
'AEM.con.elements("docu").by_index(3), ' +
|
41
|
+
'AEM.con.elements("docu").by_name("foo"))', nil],
|
42
|
+
|
43
|
+
[AEMReference::App.elements('docu').by_range(1, 'foo'),
|
44
|
+
'AEM.app.elements("docu").by_range(1, "foo")',
|
45
|
+
AEMReference::App.elements("docu").by_range(
|
46
|
+
AEMReference::Con.elements("docu").by_index(1),
|
47
|
+
AEMReference::Con.elements("docu").by_name("foo"))],
|
48
|
+
|
49
|
+
[AEMReference::Its.property('name').eq('foo').and(AEMReference::Its.elements('cwor').eq([])),
|
50
|
+
'AEM.its.property("name").eq("foo").and(AEM.its.elements("cwor").eq([]))', nil],
|
51
|
+
|
52
|
+
[AEMReference::Its.elements('cwor').ne([]),
|
53
|
+
'AEM.its.elements("cwor").ne([])',
|
54
|
+
AEMReference::Its.elements("cwor").eq([]).not], # i.e. there isn't a KAENotEqual operator, so not-equal tests are actually packed as an equal test followed by not test
|
55
|
+
|
56
|
+
[AEMReference::Its.elements('cwor').eq(nil), 'AEM.its.elements("cwor").eq(nil)', nil],
|
57
|
+
[AEMReference::Its.elements('cwor').property('leng').gt(0),
|
58
|
+
'AEM.its.elements("cwor").property("leng").gt(0)', nil],
|
59
|
+
[AEMReference::Its.elements('cwor').le(''), 'AEM.its.elements("cwor").le("")', nil],
|
60
|
+
[AEMReference::Its.elements('cwor').begins_with('foo').not,
|
61
|
+
'AEM.its.elements("cwor").begins_with("foo").not', nil],
|
62
|
+
|
63
|
+
|
64
|
+
[AEMReference::Its.elements('cwor').contains('foo'), 'AEM.its.elements("cwor").contains("foo")', nil],
|
65
|
+
[AEMReference::Its.elements('cwor').is_in('foo'), 'AEM.its.elements("cwor").is_in("foo")', nil],
|
66
|
+
|
67
|
+
[AEMReference::App.elements('docu').by_filter(AEMReference::Its.property('size').ge(42)),
|
68
|
+
'AEM.app.elements("docu").by_filter(AEM.its.property("size").ge(42))', nil],
|
69
|
+
|
70
|
+
[AEMReference::App.elements('docu').by_index(1).property('ctxt') \
|
71
|
+
.elements('cpar').elements('cha ').by_range(
|
72
|
+
AEMReference::Con.elements('cha ').by_index(3),
|
73
|
+
AEMReference::Con.elements('cha ').by_index(55)
|
74
|
+
).next('cha ').after,
|
75
|
+
'AEM.app.elements("docu").by_index(1).property("ctxt").elements("cpar").elements("cha ")' +
|
76
|
+
'.by_range(AEM.con.elements("cha ").by_index(3), AEM.con.elements("cha ").by_index(55))' +
|
77
|
+
'.next("cha ").after', nil],
|
78
|
+
|
79
|
+
[AEMReference::Its.property('pnam').ne('foo').and(AEMReference::Its.elements('cfol').eq([])).not,
|
80
|
+
'AEM.its.property("pnam").ne("foo").and(AEM.its.elements("cfol").eq([])).not',
|
81
|
+
AEMReference::Its.property('pnam').eq('foo').not.and(AEMReference::Its.elements('cfol').eq([])).not],
|
82
|
+
|
83
|
+
[AEMReference::App.elements('docu').beginning, 'AEM.app.elements("docu").beginning', nil],
|
84
|
+
[AEMReference::App.elements('docu').end, 'AEM.app.elements("docu").end', nil],
|
85
|
+
[AEMReference::App.elements('docu').by_index(3).before, 'AEM.app.elements("docu").by_index(3).before', nil],
|
86
|
+
[AEMReference::App.elements('docu').by_name('foo').after, 'AEM.app.elements("docu").by_name("foo").after', nil],
|
87
|
+
|
88
|
+
].each do |val, res, unpacked_version|
|
89
|
+
begin
|
90
|
+
assert_equal(res, val.to_s)
|
91
|
+
d = DefaultCodecs.pack(val)
|
92
|
+
val = unpacked_version ? unpacked_version : val
|
93
|
+
val2 = DefaultCodecs.unpack(d)
|
94
|
+
assert_equal(val, val2)
|
95
|
+
val2 = DefaultCodecs.unpack(d)
|
96
|
+
assert_predicate val, :eql?, val2
|
97
|
+
val2 = DefaultCodecs.unpack(d)
|
98
|
+
assert_equal(val2, val)
|
99
|
+
val2 = DefaultCodecs.unpack(d)
|
100
|
+
assert_predicate val2, :eql?, val
|
101
|
+
rescue
|
102
|
+
puts 'EXPECTED: ' + res
|
103
|
+
raise
|
104
|
+
end
|
105
|
+
end
|
106
|
+
refute_equal(AEMReference::App.property('ctxt').property('ctxt'), AEMReference::Con.property('ctxt').property('ctxt'))
|
107
|
+
refute_equal(AEMReference::App.property('foob').property('ctxt'), AEMReference::App.property('ctxt').property('ctxt'))
|
108
|
+
refute_equal(AEMReference::App.elements('ctxt').property('ctxt'), AEMReference::App.property('ctxt').property('ctxt'))
|
109
|
+
refute_equal(AEMReference::App.elements('ctxt').property('ctxt'), 333)
|
110
|
+
refute_equal(333, AEMReference::App.property('ctxt').property('ctxt'))
|
111
|
+
# # by-filter references do basic type checking to ensure an its-based reference is given
|
112
|
+
assert_raises(TypeError) { AEMReference::App.elements('docu').by_filter(1) }
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'rb-scpt'
|
5
|
+
|
6
|
+
# rb-appscript 0.5.0+ should no longer require the following kludge:
|
7
|
+
#class AS_SafeObject
|
8
|
+
# def self.hide(name)
|
9
|
+
# end
|
10
|
+
#end
|
11
|
+
|
12
|
+
class TC_AppscriptNewApp < Minitest::Test
|
13
|
+
|
14
|
+
def test_by_name
|
15
|
+
[
|
16
|
+
'/Applications/TextEdit.app',
|
17
|
+
'Finder.app',
|
18
|
+
'System Events'
|
19
|
+
].each do |name|
|
20
|
+
a = Appscript.app(name)
|
21
|
+
refute_nil(a)
|
22
|
+
assert_instance_of(Appscript::Application, a)
|
23
|
+
assert_instance_of(Appscript::Reference, a.name)
|
24
|
+
end
|
25
|
+
assert_equal('app("/Applications/TextEdit.app")', Appscript.app('TextEdit').to_s)
|
26
|
+
assert_equal('app("/Applications/TextEdit.app")', Appscript.app.by_name('TextEdit').to_s)
|
27
|
+
|
28
|
+
assert_raises(Appscript::ApplicationNotFoundError) { Appscript.app('/non-existent/app') }
|
29
|
+
assert_raises(Appscript::ApplicationNotFoundError) { Appscript.app('non-existent.app') }
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_by_id
|
33
|
+
[
|
34
|
+
'com.apple.textedit',
|
35
|
+
'com.apple.finder',
|
36
|
+
].each do |name|
|
37
|
+
a = Appscript.app.by_id(name)
|
38
|
+
refute_nil(a)
|
39
|
+
assert_instance_of(Appscript::Application, a)
|
40
|
+
assert_instance_of(Appscript::Reference, a.name)
|
41
|
+
end
|
42
|
+
assert_equal('app("/Applications/TextEdit.app")', Appscript.app.by_id('com.apple.textedit').to_s)
|
43
|
+
|
44
|
+
assert_raises(Appscript::ApplicationNotFoundError) { Appscript.app.by_id('non.existent.app') }
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_by_creator
|
48
|
+
a = Appscript.app.by_creator('ttxt')
|
49
|
+
assert_instance_of(Appscript::Reference, a.name)
|
50
|
+
assert_equal('app("/Applications/TextEdit.app")', a.to_s)
|
51
|
+
assert_raises(Appscript::ApplicationNotFoundError) { Appscript.app.by_id('!@$o') }
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_by_pid
|
55
|
+
pid = `top -l1 | grep Finder | awk '{ print $1 }'`.to_i # note: this line will return a bad result if more than one user is logged in
|
56
|
+
a = Appscript.app.by_pid(pid)
|
57
|
+
assert_instance_of(Appscript::Reference, a.name)
|
58
|
+
assert_equal("app.by_pid(#{pid})", a.to_s)
|
59
|
+
assert_equal('Finder', a.name.get)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_by_aem_app
|
63
|
+
a = Appscript.app.by_aem_app(AEM::Application.by_path('/Applications/TextEdit.app'))
|
64
|
+
assert_instance_of(Appscript::Reference, a.name)
|
65
|
+
assert_equal('app.by_aem_app(AEM::Application.by_path("/Applications/TextEdit.app"))', a.to_s)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
class TC_AppscriptCommands < Minitest::Test
|
71
|
+
|
72
|
+
def setup
|
73
|
+
@te = Appscript.app('TextEdit')
|
74
|
+
@f = Appscript.app('Finder')
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_commands_1
|
78
|
+
assert_equal('TextEdit', @te.name.get)
|
79
|
+
d = @te.make(:new=>:document, :with_properties=>{:text=>'test test_commands'})
|
80
|
+
assert_instance_of(Appscript::Reference, d)
|
81
|
+
d.text.end.make(:new=>:word, :with_data=>' test2')
|
82
|
+
assert_equal('test test_commands test2', d.text.get)
|
83
|
+
assert_instance_of(String,
|
84
|
+
d.text.get(:ignore=>[:diacriticals, :punctuation, :whitespace, :expansion], :timeout=>10))
|
85
|
+
assert_nil(d.get(:wait_reply=>false))
|
86
|
+
|
87
|
+
|
88
|
+
# test Ruby 1.9+ String Encoding support
|
89
|
+
version, sub_version = RUBY_VERSION.split('.').collect {|n| n.to_i} [0, 2]
|
90
|
+
if version >= 1 and sub_version >= 9
|
91
|
+
|
92
|
+
print "(check Encoding support)"
|
93
|
+
s = "\302\251 M. Lef\303\250vre"
|
94
|
+
s.force_encoding('utf-8')
|
95
|
+
d.text.set(s)
|
96
|
+
assert_equal(s, d.text.get)
|
97
|
+
|
98
|
+
@te.AS_app_data.use_ascii_8bit
|
99
|
+
end
|
100
|
+
|
101
|
+
d.text.set("\302\251 M. Lef\303\250vre")
|
102
|
+
assert_equal("\302\251 M. Lef\303\250vre", d.text.get)
|
103
|
+
|
104
|
+
d.close(:saving=>:no)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_commands_2
|
108
|
+
d = @te.make(:new=>:document, :at=>@te.documents.end)
|
109
|
+
|
110
|
+
@te.set(d.text, :to=> 'test1')
|
111
|
+
assert_equal('test1', d.text.get)
|
112
|
+
|
113
|
+
@te.set(d.text, :to=> 'test2')
|
114
|
+
@te.make(:new=>:word, :at=>Appscript.app.documents[1].paragraphs.end, :with_data=>' test3')
|
115
|
+
assert_equal('test2 test3', d.text.get)
|
116
|
+
|
117
|
+
d.close(:saving=>:no)
|
118
|
+
|
119
|
+
assert_raises(Appscript::CommandError) { @te.documents[10000].get }
|
120
|
+
|
121
|
+
assert_kind_of(Integer, @te.documents.count)
|
122
|
+
assert_equal(@te.documents.count, @te.count(:each=>:document))
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_commands_3
|
126
|
+
assert_equal('Finder', @f.name.get)
|
127
|
+
val = @f.home.folders['Desktop'].get(:result_type=>:alias)
|
128
|
+
assert_instance_of(MacTypes::Alias, val)
|
129
|
+
assert_equal(val, @f.desktop.get(:result_type=>:alias))
|
130
|
+
assert_instance_of(Array, @f.disks.get)
|
131
|
+
|
132
|
+
r = @f.home.get
|
133
|
+
f = r.get(:result_type=>:file_ref)
|
134
|
+
assert_equal(r, @f.items[f].get)
|
135
|
+
|
136
|
+
assert_equal(@f.home.items.get, @f.home.items.get)
|
137
|
+
refute_equal(@f.disks['non-existent'], @f.disks[1].get)
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_command_error
|
141
|
+
begin
|
142
|
+
@f.items[10000].get
|
143
|
+
rescue Appscript::CommandError => e
|
144
|
+
assert_equal(-1728, e.to_i)
|
145
|
+
assert_equal("CommandError\n\t\tOSERROR: -1728\n\t\tMESSAGE: Can't get reference.\n\t\tOFFENDING OBJECT: app(\"/System/Library/CoreServices/Finder.app\").items[10000]\n\t\tCOMMAND: app(\"/System/Library/CoreServices/Finder.app\").items[10000].get()\n", e.to_s)
|
146
|
+
assert_instance_of(AEM::EventError, e.real_error)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require "rb-scpt"
|
5
|
+
|
6
|
+
class TC_AppscriptReferences < Minitest::Test
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@te = Appscript.app('TextEdit')
|
10
|
+
@s = @te.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_reference_forms
|
14
|
+
[
|
15
|
+
|
16
|
+
[@te.documents[
|
17
|
+
Appscript.con.documents[3],
|
18
|
+
Appscript.con.documents['foo']],
|
19
|
+
@s+'.documents[' +
|
20
|
+
'con.documents[3], ' +
|
21
|
+
'con.documents["foo"]]', nil],
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
[@te.text, @s+'.text', nil],
|
26
|
+
|
27
|
+
[@te.documents, @s+'.documents', nil],
|
28
|
+
|
29
|
+
[@te.documents[1],
|
30
|
+
@s+'.documents[1]', nil],
|
31
|
+
[@te.documents['foo'],
|
32
|
+
@s+'.documents["foo"]', nil],
|
33
|
+
[@te.documents.ID(300),
|
34
|
+
@s+'.documents.ID(300)', nil],
|
35
|
+
|
36
|
+
[@te.documents.next(:document),
|
37
|
+
@s+'.documents.next(:document)', nil],
|
38
|
+
[@te.documents.previous(:document),
|
39
|
+
@s+'.documents.previous(:document)', nil],
|
40
|
+
|
41
|
+
[@te.documents.first, @s+'.documents.first', nil],
|
42
|
+
[@te.documents.middle, @s+'.documents.middle', nil],
|
43
|
+
[@te.documents.last, @s+'.documents.last', nil],
|
44
|
+
[@te.documents.any, @s+'.documents.any', nil],
|
45
|
+
|
46
|
+
[Appscript.con.documents[3], 'con.documents[3]', nil],
|
47
|
+
|
48
|
+
|
49
|
+
[Appscript.its.name.eq('foo').and(Appscript.its.words.eq([])),
|
50
|
+
'its.name.eq("foo").and(its.words.eq([]))', nil],
|
51
|
+
|
52
|
+
[Appscript.its.words.ne([]),
|
53
|
+
'its.words.ne([])',
|
54
|
+
Appscript.its.words.eq([]).not], # i.e. there isn't a KAENotEqual operator, so not-equal tests are actually packed as an equal test followed by not test
|
55
|
+
|
56
|
+
[Appscript.its.words.eq(nil), 'its.words.eq(nil)', nil],
|
57
|
+
[Appscript.its.words.size.gt(0),
|
58
|
+
'its.words.size.gt(0)', nil],
|
59
|
+
[Appscript.its.words.le(''), 'its.words.le("")', nil],
|
60
|
+
[Appscript.its.words.begins_with('foo').not,
|
61
|
+
'its.words.begins_with("foo").not', nil],
|
62
|
+
|
63
|
+
|
64
|
+
[Appscript.its.words.contains('foo'), 'its.words.contains("foo")', nil],
|
65
|
+
[Appscript.its.words.is_in('foo'), 'its.words.is_in("foo")', nil],
|
66
|
+
|
67
|
+
[@te.documents[Appscript.its.size.ge(42)],
|
68
|
+
@s+'.documents[its.size.ge(42)]', nil],
|
69
|
+
|
70
|
+
[@te.documents[1, 'foo'],
|
71
|
+
@s+'.documents[1, "foo"]',
|
72
|
+
@te.documents[Appscript.con.documents[1], Appscript.con.documents["foo"]]],
|
73
|
+
|
74
|
+
[@te.documents[1].text \
|
75
|
+
.paragraphs.characters[
|
76
|
+
Appscript.con.characters[3],
|
77
|
+
Appscript.con.characters[55]
|
78
|
+
].next(:character).after,
|
79
|
+
@s+'.documents[1].text.paragraphs.characters' +
|
80
|
+
'[con.characters[3], con.characters[55]]' +
|
81
|
+
'.next(:character).after', nil],
|
82
|
+
|
83
|
+
[Appscript.its.name.ne('foo').and(Appscript.its.words.eq([])).not,
|
84
|
+
'its.name.ne("foo").and(its.words.eq([])).not',
|
85
|
+
Appscript.its.name.eq('foo').not.and(Appscript.its.words.eq([])).not],
|
86
|
+
|
87
|
+
[@te.documents.beginning, @s+'.documents.beginning', nil],
|
88
|
+
[@te.documents.end, @s+'.documents.end', nil],
|
89
|
+
[@te.documents[3].before, @s+'.documents[3].before', nil],
|
90
|
+
[@te.documents['foo'].after, @s+'.documents["foo"].after', nil],
|
91
|
+
|
92
|
+
].each do |val, res, unpacked_version|
|
93
|
+
assert_equal(res, val.to_s)
|
94
|
+
d = @te.AS_app_data.pack(val)
|
95
|
+
val = unpacked_version ? unpacked_version : val
|
96
|
+
val2 = @te.AS_app_data.unpack(d)
|
97
|
+
if val.class == @te.AS_app_data.unpack(d).class # note: Appscript::Reference and Appscript::GenericReference currently aren't comparable with each other, so the next test would always fail for those
|
98
|
+
assert_equal(val, val2)
|
99
|
+
assert_predicate val, :eql?, val2
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/test/test_codecs.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'aem'
|
5
|
+
require 'kae'
|
6
|
+
require 'ae'
|
7
|
+
|
8
|
+
def num(s)
|
9
|
+
if [1].pack('s') == "\001\000" # host system is i386
|
10
|
+
s.reverse
|
11
|
+
else
|
12
|
+
s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def ut16(s)
|
17
|
+
if [1].pack('s') == "\001\000" # host system is i386
|
18
|
+
i = 0
|
19
|
+
s2 = ''
|
20
|
+
(s.length / 2).times do
|
21
|
+
s2 += s[i, 2].reverse
|
22
|
+
i+=2
|
23
|
+
end
|
24
|
+
s2
|
25
|
+
else
|
26
|
+
s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class TC_Codecs < Minitest::Test
|
31
|
+
|
32
|
+
def setup
|
33
|
+
@c = AEM::Codecs.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_nil
|
37
|
+
d = @c.pack(nil)
|
38
|
+
assert_equal(KAE::TypeNull, d.type)
|
39
|
+
assert_equal('', d.data)
|
40
|
+
assert_nil(@c.unpack(d))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_bool
|
44
|
+
[
|
45
|
+
[true, KAE::TypeTrue],
|
46
|
+
[false, KAE::TypeFalse]
|
47
|
+
].each do |val, type|
|
48
|
+
d = @c.pack(val)
|
49
|
+
assert_equal(type, d.type)
|
50
|
+
assert_equal('', d.data)
|
51
|
+
assert_equal(val, @c.unpack(d))
|
52
|
+
end
|
53
|
+
assert_equal(true, @c.unpack(AE::AEDesc.new(KAE::TypeBoolean, "\xfe")))
|
54
|
+
assert_equal(true, @c.unpack(AE::AEDesc.new(KAE::TypeTrue, '')))
|
55
|
+
assert_equal(false, @c.unpack(AE::AEDesc.new(KAE::TypeFalse, '')))
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_num
|
59
|
+
[ # (mostly testing at threshold points where Codecs switches types when packing integers)
|
60
|
+
[0, "\x00\x00\x00\x00", KAE::TypeInteger],
|
61
|
+
[2, "\x00\x00\x00\x02", KAE::TypeInteger],
|
62
|
+
[-9, "\xff\xff\xff\xf7", KAE::TypeInteger],
|
63
|
+
[2**31-1, "\x7f\xff\xff\xff", KAE::TypeInteger],
|
64
|
+
[-2**31, "\x80\x00\x00\x00", KAE::TypeInteger],
|
65
|
+
[2**31, "\x00\x00\x00\x00\x80\x00\x00\x00", KAE::TypeSInt64],
|
66
|
+
[2**32-1, "\x00\x00\x00\x00\xff\xff\xff\xff", KAE::TypeSInt64],
|
67
|
+
[2**32, "\x00\x00\x00\x01\x00\x00\x00\x00", KAE::TypeSInt64],
|
68
|
+
[-2**32, "\xff\xff\xff\xff\x00\x00\x00\x00", KAE::TypeSInt64],
|
69
|
+
[2**63-1, "\x7f\xff\xff\xff\xff\xff\xff\xff", KAE::TypeSInt64],
|
70
|
+
[-2**63, "\x80\x00\x00\x00\x00\x00\x00\x00", KAE::TypeSInt64],
|
71
|
+
[-2**63+1, "\x80\x00\x00\x00\x00\x00\x00\x01", KAE::TypeSInt64],
|
72
|
+
[2**63, "C\xe0\x00\x00\x00\x00\x00\x00", KAE::TypeFloat],
|
73
|
+
[-2**63-1, "\xc3\xe0\x00\x00\x00\x00\x00\x00", KAE::TypeFloat],
|
74
|
+
[0.1, "?\xb9\x99\x99\x99\x99\x99\x9a", KAE::TypeFloat],
|
75
|
+
[-0.9e-9, "\xbe\x0e\xec{\xd5\x12\xb5r", KAE::TypeFloat],
|
76
|
+
[2**300, "R\xb0\x00\x00\x00\x00\x00\x00", KAE::TypeFloat],
|
77
|
+
].each do |val, data, type|
|
78
|
+
data = num(data)
|
79
|
+
d = @c.pack(val)
|
80
|
+
assert_equal(type, d.type)
|
81
|
+
assert_equal(data, d.data)
|
82
|
+
assert_equal(val, @c.unpack(d))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_str
|
87
|
+
s = "\xc6\x92\xe2\x88\x82\xc2\xae\xd4\xb7\xd5\x96\xd4\xb9\xe0\xa8\x89\xe3\x82\xa2\xe3\x84\xbb"
|
88
|
+
# test Ruby 1.9+ String Encoding support
|
89
|
+
version, sub_version = RUBY_VERSION.split('.').collect {|n| n.to_i} [0, 2]
|
90
|
+
if version >= 1 and sub_version >= 9
|
91
|
+
s.force_encoding('utf-8')
|
92
|
+
end
|
93
|
+
|
94
|
+
[
|
95
|
+
# note: aem has to pack UTF8 data as typeUnicodeText (UTF16) as stupid apps expect that type and will error on typeUTF8Text instead of just asking AEM to coerce it to the desired type in advance.
|
96
|
+
# note: UTF16 BOM must be omitted when packing UTF16 data into typeUnicodeText AEDescs, as a BOM will upset stupid apps like iTunes 7 that don't recognise it as a BOM and treat it as character data instead
|
97
|
+
['', ''],
|
98
|
+
['hello', "\000h\000e\000l\000l\000o"],
|
99
|
+
[s, "\x01\x92\"\x02\x00\xae\x057\x05V\x059\n\t0\xa21;"],
|
100
|
+
].each do |val, data|
|
101
|
+
data = ut16(data)
|
102
|
+
d = @c.pack(val)
|
103
|
+
assert_equal(KAE::TypeUnicodeText, d.type)
|
104
|
+
assert_equal(data, d.data)
|
105
|
+
assert_equal(val, @c.unpack(d))
|
106
|
+
end
|
107
|
+
assert_raises(TypeError) { @c.pack("\x88") } # non-valid UTF8 strings should raise error when coercing from typeUTF8Text to typeUnicodeText
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_date
|
111
|
+
# note: not testing on ST-DST boundaries; this is known to have out-by-an-hour problems due to LongDateTime type being crap
|
112
|
+
[
|
113
|
+
[Time.local(2005, 12, 11, 15, 40, 43), "\x00\x00\x00\x00\xbf\xc1\xf8\xfb"],
|
114
|
+
[Time.local(2005, 5, 1, 6, 51, 7), "\x00\x00\x00\x00\xbe\x9a\x2c\xdb"],
|
115
|
+
].each do |t, data|
|
116
|
+
data = num(data)
|
117
|
+
d = @c.pack(t)
|
118
|
+
assert_equal(KAE::TypeLongDateTime, d.type)
|
119
|
+
assert_equal(data, d.data)
|
120
|
+
assert_equal(t, @c.unpack(AE::AEDesc.new(KAE::TypeLongDateTime, data)))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_file
|
125
|
+
path = '/Applications/TextEdit.app'
|
126
|
+
d = @c.pack(MacTypes::Alias.path(path))
|
127
|
+
assert_equal(path, @c.unpack(d).to_s)
|
128
|
+
|
129
|
+
path = '/Applications/TextEdit.app'
|
130
|
+
d = @c.pack(MacTypes::FileURL.path(path))
|
131
|
+
assert_equal(path, @c.unpack(d).to_s)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_typewrappers
|
135
|
+
[
|
136
|
+
AEM::AEType.new("docu"),
|
137
|
+
AEM::AEEnum.new('yes '),
|
138
|
+
AEM::AEProp.new('pnam'),
|
139
|
+
AEM::AEKey.new('ABCD'),
|
140
|
+
].each do |val|
|
141
|
+
d = @c.pack(val)
|
142
|
+
val2 = @c.unpack(d)
|
143
|
+
assert_equal(val, val2)
|
144
|
+
assert_predicate val, :eql?, val2
|
145
|
+
val2 = @c.unpack(d)
|
146
|
+
assert_equal(val2, val)
|
147
|
+
assert_predicate val2, :eql?, val
|
148
|
+
end
|
149
|
+
assert_raises(ArgumentError) { AEM::AEType.new(3) }
|
150
|
+
assert_raises(ArgumentError) { AEM::AEType.new("docum") }
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_list
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_hash
|
157
|
+
val = {'foo' => 1, AEM::AEType.new('foob') => 2, AEM::AEProp.new('barr') => 3}
|
158
|
+
expected_val = {'foo' => 1, AEM::AEType.new('foob') => 2, AEM::AEType.new('barr') => 3} # note that four-char-code keys are always unpacked as AEType
|
159
|
+
d = @c.pack(val)
|
160
|
+
assert_equal(expected_val, @c.unpack(d))
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_units
|
164
|
+
val = MacTypes::Units.new(3.3, :inches)
|
165
|
+
assert_equal(:inches, val.type)
|
166
|
+
assert_equal(3.3, val.value)
|
167
|
+
d = @c.pack(val)
|
168
|
+
assert_equal('inch', d.type)
|
169
|
+
assert_equal(3.3, @c.unpack(d.coerce(KAE::TypeFloat)))
|
170
|
+
val2 = @c.unpack(d)
|
171
|
+
assert_equal(val, val2)
|
172
|
+
assert_equal(:inches, val2.type)
|
173
|
+
assert_equal(3.3, val2.value)
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_app
|
177
|
+
val = AEM::Application.by_path(FindApp.by_name('TextEdit'))
|
178
|
+
d = @c.pack(val)
|
179
|
+
assert_equal(KAE::TypeProcessSerialNumber, d.type)
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require "_aem/findapp"
|
5
|
+
|
6
|
+
|
7
|
+
class TC_FindApp < Minitest::Test
|
8
|
+
|
9
|
+
def test_find
|
10
|
+
[
|
11
|
+
['/Applications/iCal.app', '/Applications/iCal.app'],
|
12
|
+
['ical.app', '/Applications/iCal.app'],
|
13
|
+
['ICAL', '/Applications/iCal.app'],
|
14
|
+
].each do |val, res|
|
15
|
+
assert_equal(res, FindApp.by_name(val))
|
16
|
+
end
|
17
|
+
assert_equal('/Applications/TextEdit.app', FindApp.by_creator('ttxt'))
|
18
|
+
assert_equal('/System/Library/CoreServices/Finder.app', FindApp.by_id('com.apple.finder'))
|
19
|
+
assert_raises(FindApp::ApplicationNotFoundError) { FindApp.by_name('NON-EXISTENT-APP') }
|
20
|
+
|
21
|
+
# assert_equal("/Users/has/\306\222\303\270u\314\210.app", FindApp.by_name("\306\222\303\270u\314\210.app")) # utf8 paths work ok
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require "_aem/mactypes"
|
5
|
+
|
6
|
+
|
7
|
+
class TC_MacTypes < Minitest::Test
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@path1 = `mktemp -t codecs-test`.chomp
|
11
|
+
dir, fname = File.split(@path1)
|
12
|
+
@path2 = File.join(dir, 'moved-' + fname)
|
13
|
+
# puts "path: #{@path1}" # e.g. /tmp/codecs-test.HWr1EnE3
|
14
|
+
end
|
15
|
+
|
16
|
+
def normalize(path)
|
17
|
+
return path.gsub(/\/+/, '/') # quick-n-dirty
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_alias
|
21
|
+
# make alias
|
22
|
+
f = MacTypes::Alias.path(@path1)
|
23
|
+
|
24
|
+
|
25
|
+
assert_equal(MacTypes::Alias.path(@path1), f)
|
26
|
+
|
27
|
+
# get path
|
28
|
+
# note that initial /tmp/codecs-test... path will automatically change to /private/tmp/codecs-test...
|
29
|
+
p1 = normalize('/private'+@path1)
|
30
|
+
p2 = normalize('/private'+@path2)
|
31
|
+
|
32
|
+
assert_equal(p1, normalize(f.path))
|
33
|
+
|
34
|
+
#puts "alias path 1: #{f}" # e.g. /private/tmp/codecs-test.HWr1EnE3
|
35
|
+
assert_equal(p1, f.to_s)
|
36
|
+
|
37
|
+
# get desc
|
38
|
+
#puts f.desc.type, f.desc.data # alis, [binary data]
|
39
|
+
assert_equal('alis', f.desc.type)
|
40
|
+
|
41
|
+
|
42
|
+
# check alias keeps track of moved file
|
43
|
+
`mv #{@path1} #{@path2}`
|
44
|
+
# puts "alias path 2: #{f}" # /private/tmp/moved-codecs-test.HWr1EnE3
|
45
|
+
assert_equal(p2, f.to_s)
|
46
|
+
|
47
|
+
assert_equal(p2, normalize(f.path))
|
48
|
+
|
49
|
+
# check a FileNotFoundError is raised if getting path/FileURL for a filesystem object that no longer exists
|
50
|
+
`rm #{@path2}`
|
51
|
+
assert_raises(MacTypes::FileNotFoundError) { f.to_s } # File not found.
|
52
|
+
assert_raises(MacTypes::FileNotFoundError) { f.to_file_url } # File not found.
|
53
|
+
|
54
|
+
assert_equal(MacTypes::Alias.path("/Library/Scripts/"), MacTypes::Alias.path("/Library/Scripts/"))
|
55
|
+
refute_equal(MacTypes::Alias.path("/Library/Scripts/"), MacTypes::Alias.path("/Applications/"))
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def test_file_url
|
60
|
+
|
61
|
+
g = MacTypes::FileURL.path('/non/existent path')
|
62
|
+
|
63
|
+
assert_equal('/non/existent path', g.to_s)
|
64
|
+
|
65
|
+
assert_equal('furl', g.desc.type)
|
66
|
+
assert_equal('file://localhost/non/existent%20path', g.desc.data)
|
67
|
+
|
68
|
+
assert_equal('MacTypes::FileURL.path("/non/existent path")', g.to_file_url.inspect)
|
69
|
+
|
70
|
+
# check a not-found error is raised if getting Alias for a filesystem object that doesn't exist
|
71
|
+
assert_raises(MacTypes::FileNotFoundError) { g.to_alias } # File "/non/existent path" not found.
|
72
|
+
|
73
|
+
assert_equal(MacTypes::FileURL.path("/Library/Scripts/"), MacTypes::FileURL.path("/Library/Scripts/"))
|
74
|
+
refute_equal(MacTypes::FileURL.path("/Library/Scripts/"), MacTypes::FileURL.path("/Applications/"))
|
75
|
+
refute_equal(MacTypes::FileURL.path("/Library/Scripts/"), MacTypes::Alias.path("/Library/Scripts/"))
|
76
|
+
end
|
77
|
+
end
|