rucola 0.0.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|