rucola 0.0.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +468 -0
- data/History.txt +25 -0
- data/License.txt +1 -1
- data/Manifest.txt +32 -0
- data/README.txt +9 -67
- data/Rakefile +39 -31
- data/TODO +10 -18
- data/app_generators/rucola/rucola_generator.rb +15 -8
- data/app_generators/rucola/templates/Rakefile.erb +35 -7
- data/app_generators/rucola/templates/config/boot.rb +0 -1
- data/app_generators/rucola/templates/config/dependencies.rb +31 -0
- data/app_generators/rucola/templates/config/environment.rb +0 -1
- data/app_generators/rucola/templates/config/environments/debug.rb +13 -1
- data/app_generators/rucola/templates/config/environments/release.rb +15 -1
- data/app_generators/rucola/templates/config/environments/test.rb +7 -1
- data/app_generators/rucola/templates/misc/rb_main.rb.erb +12 -1
- data/app_generators/rucola/templates/project.pbxproj.erb +4 -0
- data/app_generators/rucola/templates/script/console +10 -0
- data/app_generators/rucola/templates/test/controllers/test_application_controller.rb +22 -10
- data/app_generators/rucola/templates/test/test_helper.rb +1 -0
- data/bin/rucola +4 -2
- data/lib/rucola/dependencies.rb +241 -0
- data/lib/rucola/dependencies/exclusions.rb +20 -0
- data/lib/rucola/dependencies/override_require_and_gem.rb +30 -0
- data/lib/rucola/dependencies/resolver.rb +68 -0
- data/lib/rucola/fsevents.rb +108 -0
- data/lib/rucola/initializer.rb +149 -117
- data/lib/rucola/log.rb +61 -0
- data/lib/rucola/nib.rb +3 -3
- data/lib/rucola/reloader.rb +39 -0
- data/lib/rucola/ruby_debug.rb +27 -0
- data/lib/rucola/rucola_support.rb +1 -2
- data/lib/rucola/rucola_support/core_ext.rb +4 -2
- data/lib/rucola/rucola_support/core_ext/objc.rb +9 -4
- data/lib/rucola/rucola_support/core_ext/objc/nsimage.rb +22 -0
- data/lib/rucola/rucola_support/core_ext/ruby.rb +11 -4
- data/lib/rucola/rucola_support/core_ext/ruby/file.rb +11 -0
- data/lib/rucola/rucola_support/core_ext/ruby/kernel.rb +16 -0
- data/lib/rucola/rucola_support/core_ext/ruby/object.rb +47 -0
- data/lib/rucola/rucola_support/core_ext/ruby/string.rb +8 -0
- data/lib/rucola/rucola_support/notifications/notifications.rb +26 -28
- data/lib/rucola/rucola_support/rc_app.rb +18 -0
- data/lib/rucola/tasks/dependencies.rake +49 -0
- data/lib/rucola/tasks/deploy.rake +131 -0
- data/lib/rucola/tasks/main.rake +39 -6
- data/lib/rucola/tasks/xcode.rake +54 -11
- data/lib/rucola/test_case.rb +138 -0
- data/lib/rucola/test_helper.rb +11 -5
- data/lib/rucola/version.rb +2 -2
- data/lib/rucola/xcode.rb +39 -9
- data/rucola_generators/controller/templates/test_controller_template.rb.erb +19 -7
- data/rucola_generators/simple_model/USAGE +5 -0
- data/rucola_generators/simple_model/simple_model_generator.rb +54 -0
- data/rucola_generators/simple_model/templates/simple_model.rb.erb +2 -0
- data/rucola_generators/simple_model/templates/test_simple_model.rb.erb +11 -0
- data/rucola_generators/window_controller/templates/test_window_controller_template.rb.erb +24 -13
- data/test/fixtures/dependencies/foo.rb +2 -0
- data/test/fixtures/dependencies/foo/bar.rb +0 -0
- data/test/fixtures/dependencies/foo/baz.rb +0 -0
- data/test/fixtures/dependencies/requires_fileutils.rb +1 -0
- data/test/fixtures/some_reloadable_class.rb +4 -0
- data/test/test_core_ext.rb +80 -0
- data/test/test_dependencies.rb +205 -0
- data/test/test_fsevents.rb +152 -0
- data/test/test_helper.rb +30 -1
- data/test/test_initializer.rb +56 -23
- data/test/test_log.rb +44 -0
- data/test/test_objc_core_ext.rb +23 -0
- data/test/test_rc_app.rb +5 -0
- data/test/test_reloader.rb +28 -0
- data/test/test_rucola_generator.rb +7 -0
- data/test/test_simple_model_generator.rb +48 -0
- data/test/test_xcode.rb +85 -5
- data/website/index.html +17 -91
- data/website/index.txt +14 -81
- data/website/template.rhtml +1 -1
- 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
|
data/lib/rucola/tasks/main.rake
CHANGED
@@ -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
|
-
|
10
|
-
|
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
|
-
|
19
|
+
# Load the applications Info.plist file
|
20
|
+
INFO_PLIST = OSX::NSDictionary.dictionaryWithContentsOfFile(File.join(SOURCE_ROOT, 'Info.plist'))
|
13
21
|
|
14
|
-
|
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[(
|
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
|
data/lib/rucola/tasks/xcode.rake
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
45
|
-
|
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)
|
data/lib/rucola/test_helper.rb
CHANGED
@@ -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
|
-
#
|
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
|