rucola 0.0.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/ChangeLog +468 -0
  2. data/History.txt +25 -0
  3. data/License.txt +1 -1
  4. data/Manifest.txt +32 -0
  5. data/README.txt +9 -67
  6. data/Rakefile +39 -31
  7. data/TODO +10 -18
  8. data/app_generators/rucola/rucola_generator.rb +15 -8
  9. data/app_generators/rucola/templates/Rakefile.erb +35 -7
  10. data/app_generators/rucola/templates/config/boot.rb +0 -1
  11. data/app_generators/rucola/templates/config/dependencies.rb +31 -0
  12. data/app_generators/rucola/templates/config/environment.rb +0 -1
  13. data/app_generators/rucola/templates/config/environments/debug.rb +13 -1
  14. data/app_generators/rucola/templates/config/environments/release.rb +15 -1
  15. data/app_generators/rucola/templates/config/environments/test.rb +7 -1
  16. data/app_generators/rucola/templates/misc/rb_main.rb.erb +12 -1
  17. data/app_generators/rucola/templates/project.pbxproj.erb +4 -0
  18. data/app_generators/rucola/templates/script/console +10 -0
  19. data/app_generators/rucola/templates/test/controllers/test_application_controller.rb +22 -10
  20. data/app_generators/rucola/templates/test/test_helper.rb +1 -0
  21. data/bin/rucola +4 -2
  22. data/lib/rucola/dependencies.rb +241 -0
  23. data/lib/rucola/dependencies/exclusions.rb +20 -0
  24. data/lib/rucola/dependencies/override_require_and_gem.rb +30 -0
  25. data/lib/rucola/dependencies/resolver.rb +68 -0
  26. data/lib/rucola/fsevents.rb +108 -0
  27. data/lib/rucola/initializer.rb +149 -117
  28. data/lib/rucola/log.rb +61 -0
  29. data/lib/rucola/nib.rb +3 -3
  30. data/lib/rucola/reloader.rb +39 -0
  31. data/lib/rucola/ruby_debug.rb +27 -0
  32. data/lib/rucola/rucola_support.rb +1 -2
  33. data/lib/rucola/rucola_support/core_ext.rb +4 -2
  34. data/lib/rucola/rucola_support/core_ext/objc.rb +9 -4
  35. data/lib/rucola/rucola_support/core_ext/objc/nsimage.rb +22 -0
  36. data/lib/rucola/rucola_support/core_ext/ruby.rb +11 -4
  37. data/lib/rucola/rucola_support/core_ext/ruby/file.rb +11 -0
  38. data/lib/rucola/rucola_support/core_ext/ruby/kernel.rb +16 -0
  39. data/lib/rucola/rucola_support/core_ext/ruby/object.rb +47 -0
  40. data/lib/rucola/rucola_support/core_ext/ruby/string.rb +8 -0
  41. data/lib/rucola/rucola_support/notifications/notifications.rb +26 -28
  42. data/lib/rucola/rucola_support/rc_app.rb +18 -0
  43. data/lib/rucola/tasks/dependencies.rake +49 -0
  44. data/lib/rucola/tasks/deploy.rake +131 -0
  45. data/lib/rucola/tasks/main.rake +39 -6
  46. data/lib/rucola/tasks/xcode.rake +54 -11
  47. data/lib/rucola/test_case.rb +138 -0
  48. data/lib/rucola/test_helper.rb +11 -5
  49. data/lib/rucola/version.rb +2 -2
  50. data/lib/rucola/xcode.rb +39 -9
  51. data/rucola_generators/controller/templates/test_controller_template.rb.erb +19 -7
  52. data/rucola_generators/simple_model/USAGE +5 -0
  53. data/rucola_generators/simple_model/simple_model_generator.rb +54 -0
  54. data/rucola_generators/simple_model/templates/simple_model.rb.erb +2 -0
  55. data/rucola_generators/simple_model/templates/test_simple_model.rb.erb +11 -0
  56. data/rucola_generators/window_controller/templates/test_window_controller_template.rb.erb +24 -13
  57. data/test/fixtures/dependencies/foo.rb +2 -0
  58. data/test/fixtures/dependencies/foo/bar.rb +0 -0
  59. data/test/fixtures/dependencies/foo/baz.rb +0 -0
  60. data/test/fixtures/dependencies/requires_fileutils.rb +1 -0
  61. data/test/fixtures/some_reloadable_class.rb +4 -0
  62. data/test/test_core_ext.rb +80 -0
  63. data/test/test_dependencies.rb +205 -0
  64. data/test/test_fsevents.rb +152 -0
  65. data/test/test_helper.rb +30 -1
  66. data/test/test_initializer.rb +56 -23
  67. data/test/test_log.rb +44 -0
  68. data/test/test_objc_core_ext.rb +23 -0
  69. data/test/test_rc_app.rb +5 -0
  70. data/test/test_reloader.rb +28 -0
  71. data/test/test_rucola_generator.rb +7 -0
  72. data/test/test_simple_model_generator.rb +48 -0
  73. data/test/test_xcode.rb +85 -5
  74. data/website/index.html +17 -91
  75. data/website/index.txt +14 -81
  76. data/website/template.rhtml +1 -1
  77. metadata +120 -76
@@ -0,0 +1,131 @@
1
+ require 'uri'
2
+
3
+ namespace :deploy do
4
+ DEPLOY_NAME = "#{APPNAME}_#{APPVERSION}"
5
+ PKG = File.join('pkg', "#{DEPLOY_NAME}.dmg")
6
+
7
+ directory 'pkg'
8
+
9
+ desc "Package the application as a disk image"
10
+ task :package => :pkg do
11
+ FileUtils.rm(PKG) if File.exist?(PKG)
12
+ puts 'Creating Image...'
13
+ sh "hdiutil create -volname '#{DEPLOY_NAME}' -srcfolder 'build/Release/#{TARGET}' '#{PKG}'"
14
+ puts ''
15
+ end
16
+
17
+ desc "Write a new appcast rss file"
18
+ task :sparkle_appcast => :pkg do
19
+ check_if_sparkle_info_exists!
20
+
21
+ puts "Creating appcast..."
22
+ appcast_filename = File.basename(INFO_PLIST['SUFeedURL'])
23
+
24
+ appcast = %{
25
+ <?xml version="1.0" encoding="utf-8"?>
26
+ <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
27
+ <channel>
28
+ <title>#{APPNAME} Changelog</title>
29
+ <link>#{INFO_PLIST['SUFeedURL']}</link>
30
+ <description>#{INFO_PLIST['SUAppDescription']}</description>
31
+ <language>en</language>
32
+ <item>
33
+ <title>#{APPNAME} - #{APPVERSION}</title>
34
+ <description>#{INFO_PLIST['SUPublicReleaseNotesURL']}#{DEPLOY_NAME}_release_notes.html</description>
35
+ <pubDate>#{Time.now}</pubDate>
36
+ <enclosure url="#{INFO_PLIST['SUPublicReleaseURL']}#{DEPLOY_NAME}.dmg" length="#{File.size(PKG)}" type="application/octet-stream"/>
37
+ </item>
38
+ </channel>
39
+ </rss>}.sub(/^\n/, '')
40
+
41
+ File.open("pkg/#{appcast_filename}", 'w') { |f| f.write appcast }
42
+ puts "created: pkg/#{appcast_filename}\n\n"
43
+ end
44
+
45
+ desc "Write a new release notes html file. Looks for ReleaseNotes/#{DEPLOY_NAME}"
46
+ task :release_notes => :pkg do
47
+ begin
48
+ require 'RedCloth'
49
+ rescue LoadError
50
+ puts "Unable write the release notes html, because the RedCloth gem was not found."
51
+ exit
52
+ end
53
+
54
+ puts "Creating release notes..."
55
+
56
+ changelog = File.join(SOURCE_ROOT, 'ReleaseNotes', DEPLOY_NAME)
57
+ body = RedCloth.new(File.read(changelog))
58
+ html = %{
59
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
60
+ <html>
61
+ <body>
62
+ #{body.to_html}
63
+ </body>
64
+ </html>
65
+ }.sub(/^\n/, '').gsub(/\t/, ' ').gsub(/\n+/, "\n")
66
+
67
+ File.open("pkg/#{DEPLOY_NAME}_release_notes.html", 'w') { |f| f.write html }
68
+ puts "created: pkg/#{DEPLOY_NAME}_release_notes.html\n\n"
69
+ end
70
+
71
+ desc 'Removes the pkg/ directory.'
72
+ task :clean do
73
+ build_dir = 'pkg/'
74
+ if File.exist? build_dir
75
+ puts "Removing #{build_dir}"
76
+ FileUtils.rm_rf build_dir
77
+ end
78
+ end
79
+
80
+ desc "Upload pkg/ files. Specify the uri's with the constants PUBLISH_URI & APPCAST_URI."
81
+ task :upload do
82
+ if File.exist? PKG
83
+ puts "\nUploading: #{PKG}"
84
+ do_upload(PUBLISH_URI, PKG)
85
+ puts "\n\n"
86
+ end
87
+
88
+ appcast_path = "pkg/#{File.basename(INFO_PLIST['SUFeedURL'])}" if INFO_PLIST['SUFeedURL']
89
+ if appcast_path and File.exist?(appcast_path)
90
+ puts "\nUploading: #{appcast_path}"
91
+ do_upload(APPCAST_URI, appcast_path)
92
+ puts "\n\n"
93
+ end
94
+
95
+ release_notes_path = "pkg/#{DEPLOY_NAME}_release_notes.html"
96
+ if File.exist? release_notes_path
97
+ puts "\nUploading: #{release_notes_path}"
98
+ do_upload(APPCAST_URI, release_notes_path)
99
+ puts "\n\n"
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ def check_if_sparkle_info_exists!
106
+ [
107
+ ['SUFeedURL', 'http://mydomain.com/my_app/appcast.xml'],
108
+ ['SUAppDescription', 'My terrific application!'],
109
+ ['SUPublicReleaseNotesURL', 'http://mydomain.com/my_app/', "Don't forget the last '/' which specifies that it's a directory.\nThe constructed url would look like: http://mydomain.com/my_app/my_app_1.1_release_notes.html"],
110
+ ['SUPublicReleaseURL', 'http://mydomain.com/files/my_app/', "Don't forget the last '/' which specifies that it's a directory.\nThe constructed url would look like: http://mydomain.com/files/my_app/my_app_1.1.dmg"],
111
+ ].each { |x| check_sparkle_for_key(*x) }
112
+ end
113
+
114
+ def check_sparkle_for_key(key, example_value, notes = nil)
115
+ if INFO_PLIST[key].nil?
116
+ puts "In order to create a sparkle appcast, you need to specify the value for '#{key}' in the Info.plist file."
117
+ puts "Eg:\n\n <key>#{key}</key>\n <string>#{example_value}</string>"
118
+ puts "\nNote:\n#{notes}" if notes
119
+ exit
120
+ end
121
+ end
122
+
123
+ # calls the upload method based on the scheme
124
+ def do_upload(uri, file)
125
+ send(uri.scheme, uri, file, File.basename(file))
126
+ end
127
+
128
+ def scp(uri, file, dest_file)
129
+ sh "scp -P #{ uri.port || '22' } #{file} #{uri.userinfo}@#{uri.host}:#{uri.path}/#{dest_file}"
130
+ end
131
+ end
@@ -6,12 +6,39 @@ require 'rucola/nib'
6
6
  require 'rucola/rucola_support'
7
7
 
8
8
  # set the env, default to debug if we are running a rake task.
9
- ENV['RUBYCOCOA_ENV'] ||= 'debug'
10
- ENV['RUBYCOCOA_ROOT'] ||= SOURCE_ROOT
9
+ if ARGV[0] && %w{ release deploy }.include?(ARGV[0])
10
+ mode = 'release'
11
+ else
12
+ ENV['RUBYCOCOA_ENV'] ||= 'debug'
13
+ ENV['RUBYCOCOA_ROOT'] ||= SOURCE_ROOT
14
+
15
+ mode = ENV['RUBYCOCOA_ENV']
16
+ end
17
+ puts "Running in mode: #{mode}\n\n"
11
18
 
12
- require 'rucola/initializer'
19
+ # Load the applications Info.plist file
20
+ INFO_PLIST = OSX::NSDictionary.dictionaryWithContentsOfFile(File.join(SOURCE_ROOT, 'Info.plist'))
13
21
 
14
- puts "RUNNING IN MODE: #{RUBYCOCOA_ENV.upcase}\n\n"
22
+ # Set some application defaults for the rake tasks
23
+ APPNAME = INFO_PLIST['CFBundleExecutable']
24
+ APPVERSION = INFO_PLIST['CFBundleVersion']
25
+ TARGET = "#{APPNAME}.app"
26
+
27
+ # Now that the env is set let initializer do it's work
28
+ require 'rucola/initializer'
29
+ # Load the configuration
30
+ module Rucola
31
+ class Initializer
32
+ class << self
33
+ def run
34
+ yield instance.configuration
35
+ end
36
+ end
37
+ end
38
+ end
39
+ CONFIGURATION = Rucola::Configuration.new
40
+ Rucola::Initializer.instance.instance_variable_set(:@configuration, CONFIGURATION)
41
+ CONFIGURATION.load_environment_configuration!
15
42
 
16
43
  # FIXME: We also need to check if the user uses a frozen rc framework
17
44
  RUBYCOCOA_FRAMEWORK = OSX::NSBundle.bundleWithIdentifier('com.apple.rubycocoa').bundlePath.to_s
@@ -20,14 +47,20 @@ RUBYCOCOA_FRAMEWORK = OSX::NSBundle.bundleWithIdentifier('com.apple.rubycocoa').
20
47
 
21
48
  # Get all the tasks
22
49
  Dir["#{File.dirname(__FILE__)}/*.rake"].each {|file| load file unless ['main.rake'].include? File.basename(file) }
23
- Dir[(ENV['RUBYCOCOA_ROOT'] + '/vendor/plugins/*/tasks/*.rake').to_s].each { |r| load r }
50
+ Dir[(SOURCE_ROOT + '/vendor/plugins/*/tasks/*.rake').to_s].each { |r| load r }
51
+
24
52
  task :default => 'xcode:build'
25
53
 
26
54
  desc 'Runs all the clean tasks'
27
- task :clean => 'xcode:clean'
55
+ task :clean => ['xcode:clean', 'dependencies:clean', 'deploy:clean']
28
56
 
29
57
  Rake::TestTask.new do |t|
30
58
  t.test_files = FileList['test/*/test_*.rb']
31
59
  t.options = '-rr'
32
60
  t.verbose = true
33
61
  end
62
+
63
+ desc 'Update any missing/changed files, if you updated from an earlier version of Rucola.1'
64
+ task :update do
65
+ sh "cd .. && rucola #{File.basename(SOURCE_ROOT)}"
66
+ end
@@ -1,3 +1,10 @@
1
+ desc "Shortcut for doing a release build"
2
+ task :release do
3
+ RUBYCOCOA_ENV = 'release'
4
+ Rake::Task['xcode:build'].invoke
5
+ end
6
+
7
+ # we should probably rename this namespace and task to 'build'
1
8
  namespace :xcode do
2
9
 
3
10
  def config
@@ -8,27 +15,36 @@ namespace :xcode do
8
15
  # get the users build dir
9
16
  prefs = OSX::NSUserDefaults.standardUserDefaults
10
17
  prefs.addSuiteNamed 'com.apple.xcode'
11
- prefs['PBXApplicationwideBuildSettings']['SYMROOT'] || './build'
18
+ # first check if there are any xcode prefs at all.
19
+ if prefs['PBXApplicationwideBuildSettings']
20
+ prefs['PBXApplicationwideBuildSettings']['SYMROOT'] || './build'
21
+ else
22
+ './build'
23
+ end
12
24
  end
13
25
 
14
26
  def build_root
15
27
  File.expand_path("#{build_dir}/#{config}/#{TARGET}")
16
28
  end
17
29
 
30
+ def executable
31
+ "#{build_root}/Contents/MacOS/#{APPNAME}"
32
+ end
33
+
18
34
  desc 'Builds the application'
19
35
  task :build do
20
- executable = "#{build_root}/Contents/MacOS/#{APPNAME}"
36
+ # First check if we're in release and need to bundle anything
37
+ Rake::Task['dependencies:copy'].invoke if RUBYCOCOA_ENV == 'release'
21
38
 
22
39
  # For now let's do xcodebuild everytime.
23
40
  # Otherwise nibs that are updated will not be updated in the bundle...
24
41
  sh "xcodebuild -configuration #{config}"
25
42
 
26
- # unless File.exists?(executable)
27
- # sh "xcodebuild -configuration #{config}"
28
- # else
29
- # puts "Build already exists, skipping. (Use clean if you really really want a new build.)\n\n"
30
- # end
31
-
43
+ Rake::Task['xcode:run'].invoke unless ENV['DONT_START_RUBYCOCOA_APP']
44
+ end
45
+
46
+ desc 'Run a build'
47
+ task :run do
32
48
  # Make sure the app is brought to the front once launched.
33
49
  Thread.new(executable) do |executable|
34
50
  sleep 0.025 until OSX::NSWorkspace.sharedWorkspace.launchedApplications.any? {|dict| dict['NSApplicationName'] == APPNAME }
@@ -36,12 +52,39 @@ namespace :xcode do
36
52
  end
37
53
 
38
54
  # launch app with the correct env set
39
- sh "RUBYCOCOA_ENV='#{RUBYCOCOA_ENV}' RUBYCOCOA_ROOT='#{RUBYCOCOA_ROOT}' #{executable}"
55
+ if RUBYCOCOA_ENV == 'release'
56
+ sh executable
57
+ else
58
+ sh "RUBYCOCOA_ENV='#{RUBYCOCOA_ENV}' RUBYCOCOA_ROOT='#{RUBYCOCOA_ROOT}' #{executable}"
59
+ end
40
60
  end
41
61
 
42
62
  desc 'Removes the build'
43
63
  task :clean do
44
- puts "Removing #{build_root}"
45
- FileUtils.rm_rf build_root
64
+ if File.exist? build_dir
65
+ puts "Removing #{build_dir}"
66
+ FileUtils.rm_rf build_dir
67
+ end
68
+ end
69
+
70
+ namespace :frameworks do
71
+ desc "Add any framework in vendor/frameworks which isn't in the project yet to the project and bundle it"
72
+ task :update do
73
+ if File.exist? 'vendor/frameworks'
74
+ project = Rucola::Xcode.new File.join(SOURCE_ROOT, "#{APPNAME}.xcodeproj")
75
+ framework_names = project.frameworks.map { |f| f.last['name'] }
76
+ changes = false
77
+ FileList['vendor/frameworks/*.framework'].each do |framework|
78
+ framework_name = File.basename(framework)
79
+ unless framework_names.include?(framework_name)
80
+ changes = true
81
+ puts "Adding #{framework_name} to project."
82
+ project.add_framework(framework_name, framework)
83
+ project.bundle_framework(framework_name)
84
+ end
85
+ end
86
+ project.save if changes
87
+ end
88
+ end
46
89
  end
47
90
  end
@@ -0,0 +1,138 @@
1
+ class OSX::NSObject
2
+ class << self
3
+ # An array of defined ib_outlets.
4
+ #
5
+ # Only used in test cases.
6
+ def defined_ib_outlets
7
+ @defined_ib_outlets ||= []
8
+ end
9
+
10
+ # Override ib_outlets so we can store which ones need to be defined.
11
+ #
12
+ # Only used in test cases.
13
+ def ib_outlets(*outlets)
14
+ defined_ib_outlets.concat(outlets.flatten)
15
+ end
16
+ alias_method :ib_outlet, :ib_outlets
17
+ end
18
+ end
19
+
20
+ module Rucola
21
+ module TestCase
22
+ # Defines the controller that will be tested.
23
+ #
24
+ # class ApplicationController < OSX::NSObject
25
+ # ib_outlet :window
26
+ # ib_outlets :tableView, :searchField
27
+ # ib_outlets :textField
28
+ # end
29
+ #
30
+ # class TestFoo < Test::Unit::TestCase
31
+ # tests ApplicationController
32
+ #
33
+ # def after_setup
34
+ # ib_outlets :window => mock("Main Window"),
35
+ # :tableView => OSX::NSTableView.alloc.init,
36
+ # :searchField => OSX::NSSearchField.alloc.init
37
+ #
38
+ # window.stubs(:title => 'Main Window')
39
+ # tableView.addTableColumn OSX::NSTableColumn.alloc.init
40
+ # searchField.stringValue = "foo"
41
+ # end
42
+ #
43
+ # def test_something
44
+ # p controller # => #<ApplicationController:0xdfa1ce class='ApplicationController' id=0x1e8d0e0>
45
+ # p window.title # => "Main Window"
46
+ # p tableView.tableColumns # => #<NSCFArray [#<OSX::NSTableColumn:0xdf9d0a class='NSTableColumn' id=0x1e90d00>]>
47
+ # p searchField # => #<OSX::NSSearchField:0xdfa43a class='NSSearchField' id=0x1e84cb0>
48
+ #
49
+ # # Note that we haven't set the textField ib_outlet to anything else in the after_setup method,
50
+ # # so it will be a stub which responds to everything by returning nil.
51
+ # p textField # => #<Mock:textField>
52
+ # end
53
+ # end
54
+ def tests(class_to_be_tested)
55
+ @class_to_be_tested = class_to_be_tested
56
+ include Rucola::TestCase::InstanceMethods
57
+ end
58
+
59
+ module InstanceMethods
60
+ # Sets up the ib_outlets to all be stubs which respond to everything with nil.
61
+ #
62
+ # In your test use #after_setup to do any custom setup.
63
+ def setup
64
+ class_to_be_tested.defined_ib_outlets.each do |outlet|
65
+ ib_outlet(outlet, stub_everything(outlet.to_s))
66
+ end
67
+ after_setup if respond_to? :after_setup
68
+ end
69
+
70
+ # Sets the ib_outlets and instance to be tested to nil at the end of the test.
71
+ #
72
+ # In your test use #after_teardown to do any custom teardown.
73
+ def teardown
74
+ class_to_be_tested.defined_ib_outlets.each do |outlet|
75
+ instance_to_be_tested.instance_variable_set("@#{outlet}", nil)
76
+ end
77
+ @instance_to_be_tested = nil
78
+ after_teardown if respond_to? :after_teardown
79
+ end
80
+
81
+ # Returns the class that's to be tested.
82
+ def class_to_be_tested
83
+ self.class.instance_variable_get(:@class_to_be_tested)
84
+ end
85
+
86
+ # An instance of the class that's to be tested.
87
+ def instance_to_be_tested
88
+ @instance_to_be_tested ||= class_to_be_tested.alloc.init
89
+ end
90
+ alias_method :controller, :instance_to_be_tested
91
+
92
+ # Lets you get an instance variable from the instance.
93
+ #
94
+ # obj.instance_variable_set(:@some_attr, 'foo')
95
+ # assigns(:some_attr) # => 'foo'
96
+ #
97
+ # You can also set an instance variable in the instance.
98
+ #
99
+ # obj.assigns(:some_attr, 'bar')
100
+ # obj.instance_variable_get(:@some_attr) # => 'bar'
101
+ def assigns(name, obj = nil)
102
+ obj.nil? ? instance_to_be_tested.instance_variable_get("@#{name}") : instance_to_be_tested.instance_variable_set("@#{name}", obj)
103
+ end
104
+
105
+ # Defines instance variables in the instance which represent the ib_outlets.
106
+ # It basically just sets the instance variables, but also creates shorcut accessors to get at them from your tests.
107
+ #
108
+ # def after_setup
109
+ # ib_outlet :textField, OSX::NSTextField.alloc.init
110
+ # p textField # => #<OSX::NSTextField:0xdfa3f4 class='NSTextField' id=0x1e842b0>
111
+ # end
112
+ #
113
+ # Note that not every class can be instantiated in a test.
114
+ # So you can also supply something like a mock.
115
+ def ib_outlet(name, obj)
116
+ unless respond_to? name
117
+ self.class.class_eval do
118
+ define_method(name) { assigns(name) }
119
+ private name
120
+ end
121
+ end
122
+ assigns(name, obj)
123
+ end
124
+
125
+ # Shortcut method to defined multiple ib_outlets by supplying a hash.
126
+ #
127
+ # def after_setup
128
+ # ib_outlets :window => mock("Main Window"),
129
+ # :tableView => OSX::NSTableView.alloc.init,
130
+ # :searchField => OSX::NSSearchField.alloc.init
131
+ # end
132
+ def ib_outlets(outlets)
133
+ outlets.each {|k,v| ib_outlet(k, v) }
134
+ end
135
+ end
136
+ end
137
+ end
138
+ Test::Unit::TestCase.send(:extend, Rucola::TestCase)
@@ -9,12 +9,10 @@ class Object
9
9
  end
10
10
  end
11
11
 
12
- module OSX
12
+ module OSX #:nodoc:
13
13
  # Allows methods to be overriden with a different arity.
14
14
  #
15
- # TODO: Check with Laurent if this is bad?
16
- # Otherwise we should maybe override the stub method to set this to true
17
- # when the object is a subclass of OSX::NSObject and set it to false again after the stubbing.
15
+ # FIXME: This seems to destroy the #super_init etc from working
18
16
  def self._ignore_ns_override; true; end
19
17
 
20
18
  class NSObject
@@ -68,4 +66,12 @@ module OSX
68
66
  res
69
67
  end
70
68
  end
71
- end
69
+ end
70
+
71
+ # Sets the RUBYCOCOA_ENV for the duration of the block.
72
+ def with_env(env)
73
+ before = Rucola::RCApp.env
74
+ Rucola::RCApp.stubs(:env).returns(env)
75
+ yield
76
+ Rucola::RCApp.stubs(:env).returns(before)
77
+ end