rucola 0.0.1 → 0.0.2
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 +301 -0
- data/History.txt +51 -0
- data/Manifest.txt +12 -0
- data/README.txt +6 -7
- data/TODO +13 -8
- data/app_generators/rucola/rucola_generator.rb +1 -1
- data/app_generators/rucola/templates/app/controllers/application_controller.rb +2 -2
- data/app_generators/rucola/templates/test/controllers/test_application_controller.rb +22 -5
- data/app_generators/rucola/templates/test/test_helper.rb +3 -2
- data/config/hoe.rb +2 -2
- data/lib/autotest/discover.rb +9 -0
- data/lib/autotest/fail.png +0 -0
- data/lib/autotest/growl_images.rb +39 -0
- data/lib/autotest/pass.png +0 -0
- data/lib/autotest/rucola.rb +36 -0
- data/lib/autotest/sound.rb +52 -0
- data/lib/rucola/info_plist.rb +5 -0
- data/lib/rucola/initializer.rb +65 -113
- data/lib/rucola/nib.rb +2 -2
- data/lib/rucola/plugin.rb +57 -0
- data/lib/rucola/rucola_support/initialize_hooks.rb +7 -0
- data/lib/rucola/rucola_support/notifications/notifications.rb +67 -27
- data/lib/rucola/rucola_support/rc_app.rb +9 -0
- data/lib/rucola/tasks/main.rake +8 -4
- data/lib/rucola/tasks/xcode.rake +10 -6
- data/lib/rucola/test_helper.rb +14 -0
- data/lib/rucola/version.rb +1 -1
- data/lib/rucola/xcode.rb +11 -6
- data/rucola_generators/controller/controller_generator.rb +1 -1
- data/rucola_generators/controller/templates/test_controller_template.rb.erb +14 -5
- data/rucola_generators/document_model/document_model_generator.rb +3 -3
- data/rucola_generators/document_model/templates/test_document_model_template.rb.erb +18 -5
- data/rucola_generators/rucola_plugin/USAGE +6 -0
- data/rucola_generators/rucola_plugin/rucola_plugin_generator.rb +63 -0
- data/rucola_generators/rucola_plugin/templates/init.rb.erb +25 -0
- data/rucola_generators/window_controller/templates/test_window_controller_template.rb.erb +21 -5
- data/rucola_generators/window_controller/window_controller_generator.rb +1 -1
- data/test/test_document_model_generator.rb +8 -2
- data/test/test_info_plist.rb +4 -0
- data/test/test_initializer.rb +80 -0
- data/test/test_nib.rb +9 -0
- data/test/test_notifications.rb +38 -19
- data/test/test_plugin.rb +48 -0
- data/test/test_rc_app.rb +5 -0
- data/test/test_rucola_plugin_generator.rb +65 -0
- data/test/test_xcode.rb +3 -3
- data/website/index.html +49 -7
- data/website/index.txt +34 -4
- metadata +37 -2
@@ -1,10 +1,23 @@
|
|
1
1
|
require File.expand_path('../../test_helper', __FILE__)
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
describe '<%= name.camel_case %>' do
|
4
|
+
before do
|
5
|
+
@document = <%= name.camel_case %>.alloc.init
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should initialize" do
|
9
|
+
@document.should.be.an.instance_of <%= name.camel_case %>
|
10
|
+
|
11
|
+
# You can also test if your attributes were set correctly in #after_init.
|
12
|
+
# @document.some_attr.should == 'default'
|
8
13
|
end
|
9
14
|
|
15
|
+
it "should do stuff when a document is opened" do
|
16
|
+
# Some example code of testing your #readFromFile_ofType method.
|
17
|
+
# The same goes for the alternative open/write methods.
|
18
|
+
#
|
19
|
+
# path = '/some/path/to/a/textfile.txt'
|
20
|
+
# File.expects(:read).with(path).returns('foo')
|
21
|
+
# @document.readFromFile_ofType(path, '????')
|
22
|
+
end
|
10
23
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rucola/rucola_support'
|
2
|
+
|
3
|
+
class RucolaPluginGenerator < RubiGen::Base
|
4
|
+
|
5
|
+
default_options :author => nil
|
6
|
+
|
7
|
+
attr_reader :name, :plugin_name
|
8
|
+
|
9
|
+
def initialize(runtime_args, runtime_options = {})
|
10
|
+
super
|
11
|
+
usage if args.empty?
|
12
|
+
@name = args.shift.snake_case
|
13
|
+
@plugin_name = @name.camel_case
|
14
|
+
extract_options
|
15
|
+
end
|
16
|
+
|
17
|
+
def manifest
|
18
|
+
record do |m|
|
19
|
+
plugin_dir = "vendor/plugins/#{name}"
|
20
|
+
# Ensure appropriate folder(s) exists
|
21
|
+
m.directory plugin_dir
|
22
|
+
m.directory "#{plugin_dir}/generators"
|
23
|
+
m.directory "#{plugin_dir}/lib"
|
24
|
+
m.directory "#{plugin_dir}/tasks"
|
25
|
+
if @rspec
|
26
|
+
m.directory "#{plugin_dir}/spec"
|
27
|
+
else
|
28
|
+
m.directory "#{plugin_dir}/test"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Create stubs
|
32
|
+
m.template "init.rb.erb", "#{plugin_dir}/init.rb"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def banner
|
38
|
+
<<-EOS
|
39
|
+
Creates a Rucola plugin in your apps vendor/plugins directory.
|
40
|
+
|
41
|
+
!!! NOTE: Rucola is still very young, and we may (will probably) modify how plugins work.
|
42
|
+
!!! Please give feedback on the mailing list or in #ruby-osx on freenode
|
43
|
+
|
44
|
+
USAGE: #{$0} #{spec.name} name
|
45
|
+
EOS
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_options!(opts)
|
49
|
+
opts.separator ''
|
50
|
+
opts.separator 'Options:'
|
51
|
+
# For each option below, place the default
|
52
|
+
# at the top of the file next to "default_options"
|
53
|
+
opts.on("-r", "--rspec", "Create spec directory rather than test") { |v| options[:rspec] = v }
|
54
|
+
# opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
|
55
|
+
end
|
56
|
+
|
57
|
+
def extract_options
|
58
|
+
# for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
|
59
|
+
# Templates can access these value via the attr_reader-generated methods, but not the
|
60
|
+
# raw instance variable value.
|
61
|
+
@rspec = options[:rspec]
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'osx/cocoa'
|
2
|
+
require 'rucola/plugin'
|
3
|
+
|
4
|
+
module Rucola
|
5
|
+
class <%= plugin_name %> < Plugin
|
6
|
+
def before_boot
|
7
|
+
end
|
8
|
+
|
9
|
+
def after_boot
|
10
|
+
end
|
11
|
+
|
12
|
+
def before_process(initializer)
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_process(initializer)
|
16
|
+
end
|
17
|
+
|
18
|
+
def after_launch
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Configuration
|
23
|
+
# Add anything you need to the configuration here.
|
24
|
+
end
|
25
|
+
end
|
@@ -1,10 +1,26 @@
|
|
1
1
|
require File.expand_path('../../test_helper', __FILE__)
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
describe '<%= name.camel_case %>Controller' do
|
4
|
+
before do
|
5
|
+
@controller = <%= name.camel_case %>Controller.alloc.init
|
6
|
+
|
7
|
+
# If this is a window controller belonging to a document model,
|
8
|
+
# then this will allow you to mock the document.
|
9
|
+
#
|
10
|
+
# @document = mock('Document')
|
11
|
+
# @controller.stubs(:document).returns(@document)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should initialize" do
|
15
|
+
@controller.should.be.an.instance_of <%= name.camel_case %>Controller
|
8
16
|
end
|
9
17
|
|
18
|
+
it "should do stuff at awakeFromNib" do
|
19
|
+
# Some example code of testing your #awakeFromNib.
|
20
|
+
#
|
21
|
+
# @document.expects(:some_method).returns('foo')
|
22
|
+
# @controller.ib_outlet(:some_text_view).expects(:string=).with('foo')
|
23
|
+
|
24
|
+
@controller.awakeFromNib
|
25
|
+
end
|
10
26
|
end
|
@@ -25,14 +25,20 @@ class TestDocumentModelGenerator < Test::Unit::TestCase
|
|
25
25
|
# bare_setup - place this in setup method to create the APP_ROOT folder for each test
|
26
26
|
# bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test
|
27
27
|
|
28
|
-
def
|
28
|
+
def test_generator_without_extension
|
29
|
+
name = "MyDocument"
|
30
|
+
proc { run_generator('document_model', [name], sources) }.should.raise RubiGen::UsageError
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_generator_with_correct_options
|
29
34
|
name = "MyDocument"
|
30
35
|
extension = 'mydocext'
|
31
36
|
|
32
37
|
plist_mock = mock('Info Plist')
|
33
38
|
OSX::NSDictionary.expects(:dictionaryWithContentsOfFile).returns(plist_mock)
|
34
39
|
doc_types = []
|
35
|
-
plist_mock.expects(:[]).
|
40
|
+
plist_mock.expects(:[]=).at_least_once.returns(doc_types)
|
41
|
+
plist_mock.expects(:[]).at_least_once.with('CFBundleDocumentTypes').returns(doc_types)
|
36
42
|
plist_mock.expects(:writeToFile_atomically)
|
37
43
|
|
38
44
|
run_generator('document_model', [name, extension], sources)
|
data/test/test_info_plist.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
require 'rucola/initializer'
|
3
|
+
|
4
|
+
RUBYCOCOA_ROOT = Pathname.new('/MyApp')
|
5
|
+
|
6
|
+
describe "Initializer's Class methods" do
|
7
|
+
# it "should load the plugins directly after loading the initializer file" do
|
8
|
+
# Rucola::Initializer.expects(:load_plugins)
|
9
|
+
# load 'rucola/initializer.rb'
|
10
|
+
# end
|
11
|
+
|
12
|
+
it "should return the path to the plugins root directory" do
|
13
|
+
Rucola::Initializer.plugins_root.to_s.should == '/MyApp/vendor/plugins'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should load any plugins by requiring their init.rb files" do
|
17
|
+
plugin_root_mock = mock('Plugin Root')
|
18
|
+
Rucola::Initializer.expects(:plugins_root).returns(plugin_root_mock)
|
19
|
+
plugin_root_mock.expects(:exist?).returns(true)
|
20
|
+
|
21
|
+
dir_mock, file_mock = mock('Dir'), mock('File')
|
22
|
+
plugin_root_mock.expects(:children).returns([file_mock, dir_mock])
|
23
|
+
|
24
|
+
file_mock.expects(:directory?).returns(false)
|
25
|
+
dir_mock.expects(:directory?).returns(true)
|
26
|
+
|
27
|
+
init_rb_path = '/MyApp/vendor/plugins/Foo/init.rb'
|
28
|
+
dir_mock.expects(:+).with('init.rb').returns(init_rb_path)
|
29
|
+
Kernel.expects(:require).with(init_rb_path)
|
30
|
+
|
31
|
+
Rucola::Initializer.load_plugins
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should run any before and after boot plugins around the call to do_boot" do
|
35
|
+
Rucola::Plugin.expects(:before_boot)
|
36
|
+
Rucola::Initializer.expects(:do_boot)
|
37
|
+
Rucola::Plugin.expects(:after_boot)
|
38
|
+
Rucola::Initializer.boot
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should perform the application's specific configuration and start the app" do
|
42
|
+
config_mock = mock('Configuration')
|
43
|
+
Rucola::Configuration.expects(:new).returns(config_mock)
|
44
|
+
initializer_mock = mock('Initializer')
|
45
|
+
Rucola::Initializer.expects(:new).with(config_mock).returns(initializer_mock)
|
46
|
+
initializer_mock.expects(:process)
|
47
|
+
Rucola::Initializer.expects(:start_app)
|
48
|
+
|
49
|
+
Rucola::Initializer.run
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should yield the configuration instance for setup purposes (this is used in the environments)" do
|
53
|
+
config_mock = mock('Configuration')
|
54
|
+
Rucola::Configuration.expects(:new).returns(config_mock)
|
55
|
+
Rucola::Initializer.any_instance.expects(:process)
|
56
|
+
Rucola::Initializer.expects(:start_app)
|
57
|
+
|
58
|
+
Rucola::Initializer.run do |config|
|
59
|
+
config.should.be config_mock
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should actually start the main app run loop" do
|
64
|
+
OSX.expects(:NSApplicationMain)
|
65
|
+
Rucola::Initializer.start_app
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should not start the main app run loop if the RUBYCOCOA_ENV is 'test'" do
|
69
|
+
::RUBYCOCOA_ENV = 'test'
|
70
|
+
OSX.expects(:NSApplicationMain).times(0)
|
71
|
+
Rucola::Initializer.start_app
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should not start the main app run loop if ENV['DONT_START_RUBYCOCOA_APP'] has been set" do
|
75
|
+
::RUBYCOCOA_ENV = 'release'
|
76
|
+
ENV['DONT_START_RUBYCOCOA_APP'] = 'true'
|
77
|
+
OSX.expects(:NSApplicationMain).times(0)
|
78
|
+
Rucola::Initializer.start_app
|
79
|
+
end
|
80
|
+
end
|
data/test/test_nib.rb
CHANGED
@@ -34,6 +34,15 @@ describe 'Nib::Classes' do
|
|
34
34
|
@nib.classes.last.to_ruby.should == { 'CLASS' => 'FooController', "LANGUAGE"=>"ObjC", "SUPERCLASS"=>"NSObject" }
|
35
35
|
end
|
36
36
|
|
37
|
+
it "should be able to add a subclass of a specific class" do
|
38
|
+
before = @nib.classes.length
|
39
|
+
@nib.add_class('JoesController', 'MomsController')
|
40
|
+
@nib.classes.length.should.be before + 1
|
41
|
+
|
42
|
+
@nib.classes.last.to_ruby.should == { 'CLASS' => 'JoesController', "LANGUAGE"=>"ObjC", "SUPERCLASS"=>"MomsController" }
|
43
|
+
|
44
|
+
end
|
45
|
+
|
37
46
|
it "should be able to save the classes.nib" do
|
38
47
|
Rucola::Nib.expects(:backup).with(@path)
|
39
48
|
@nib.data.expects(:writeToFile_atomically).with(@path, true)
|
data/test/test_notifications.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
2
|
|
3
3
|
class FooNotifiable < Rucola::RCController; end
|
4
|
-
class BarNotifiable < Rucola::RCController; end
|
5
|
-
class BazNotifiable < Rucola::RCController; end
|
6
|
-
class BlaNotifiable < Rucola::RCController; end
|
7
|
-
class FuNotifiable < Rucola::RCController; end
|
8
|
-
class KungNotifiable < Rucola::RCController; end
|
9
4
|
class Person < Rucola::RCController; end
|
5
|
+
class Shipping < Rucola::RCController
|
6
|
+
notify :update_shipping, :when => :address_was_changed
|
7
|
+
def update_shipping(notification); end
|
8
|
+
end
|
10
9
|
|
11
10
|
describe 'Rucola::Notifications' do
|
11
|
+
after do
|
12
|
+
OSX::NSNotificationCenter.defaultCenter.removeObserver(@instance)
|
13
|
+
end
|
14
|
+
|
12
15
|
it "should handle notifications when included" do
|
13
16
|
FooNotifiable.instance_variable_get(:@_registered_notifications).should.be.nil
|
14
17
|
|
@@ -26,50 +29,66 @@ describe 'Rucola::Notifications' do
|
|
26
29
|
end
|
27
30
|
|
28
31
|
it "should be able to handle the original string representations of the notifications" do
|
29
|
-
|
32
|
+
FooNotifiable.notify_on 'NSApplicationDidFinishLaunchingNotification' do |notification|
|
30
33
|
app_finished_launching
|
31
34
|
end
|
32
35
|
|
33
|
-
|
36
|
+
@instance = FooNotifiable.alloc.init
|
37
|
+
@instance.expects(:app_finished_launching)
|
34
38
|
OSX::NSNotificationCenter.defaultCenter.postNotificationName_object(OSX::NSApplicationDidFinishLaunchingNotification, self)
|
35
39
|
end
|
36
40
|
|
37
41
|
it "should also be able to handle the abbreviated symbol representation of a notification" do
|
38
|
-
|
42
|
+
FooNotifiable.notify_on :application_did_become_active do |notification|
|
39
43
|
app_did_become_active
|
40
44
|
end
|
41
45
|
|
42
|
-
|
46
|
+
@instance = FooNotifiable.alloc.init
|
47
|
+
@instance.expects(:app_did_become_active)
|
43
48
|
OSX::NSNotificationCenter.defaultCenter.postNotificationName_object(OSX::NSApplicationDidBecomeActiveNotification, self)
|
44
49
|
end
|
45
50
|
|
46
|
-
it "should raise a NameError exception if the abbreviated notification wasn't found" do
|
47
|
-
lambda { BlaNotifiable.notify_on :does_not_exist do |notification|; end }.should.raise NameError
|
48
|
-
end
|
49
|
-
|
50
51
|
it "should also allow the user to define shortcuts" do
|
51
|
-
|
52
|
+
FooNotifiable.notification_prefix :win => :window
|
52
53
|
|
53
|
-
|
54
|
+
FooNotifiable.notify_on :win_did_become_key do |notification|
|
54
55
|
window_did_become_key
|
55
56
|
end
|
56
|
-
|
57
|
-
|
57
|
+
|
58
|
+
@instance = FooNotifiable.alloc.init
|
59
|
+
@instance.expects(:window_did_become_key)
|
58
60
|
OSX::NSNotificationCenter.defaultCenter.postNotificationName_object(OSX::NSWindowDidBecomeKeyNotification, self)
|
59
61
|
end
|
60
62
|
|
61
63
|
it "should by default have the shortcut app => application" do
|
62
|
-
|
64
|
+
FooNotifiable.notify_on :app_will_terminate do |notification|
|
63
65
|
app_will_terminate_called!
|
64
66
|
end
|
65
67
|
|
66
|
-
|
68
|
+
@instance = FooNotifiable.alloc.init
|
69
|
+
@instance.expects(:app_will_terminate_called!)
|
67
70
|
OSX::NSNotificationCenter.defaultCenter.postNotificationName_object(OSX::NSApplicationWillTerminateNotification, self)
|
68
71
|
end
|
69
72
|
|
73
|
+
it "should also work with `once` instead of `notify_on`" do
|
74
|
+
FooNotifiable.once :app_did_become_active do |notification|
|
75
|
+
app_did_become_active!
|
76
|
+
end
|
77
|
+
|
78
|
+
@instance = FooNotifiable.alloc.init
|
79
|
+
@instance.expects(:app_did_become_active!)
|
80
|
+
OSX::NSNotificationCenter.defaultCenter.postNotificationName_object(OSX::NSApplicationDidBecomeActiveNotification, self)
|
81
|
+
end
|
82
|
+
|
70
83
|
it "should call a given method when a certain notification is called" do
|
71
84
|
Person.notify :method_to_notify, :when => 'MyNotification'
|
72
85
|
Person.alloc.init.expects(:method_to_notify)
|
73
86
|
OSX::NSNotificationCenter.defaultCenter.postNotificationName_object("MyNotification", nil)
|
74
87
|
end
|
88
|
+
|
89
|
+
it "should fire notifications" do
|
90
|
+
shipping = Shipping.alloc.init
|
91
|
+
shipping.expects(:update_shipping)
|
92
|
+
Shipping.fire_notification(:address_was_changed, nil)
|
93
|
+
end
|
75
94
|
end
|
data/test/test_plugin.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
require 'rucola/plugin'
|
3
|
+
|
4
|
+
include Rucola
|
5
|
+
|
6
|
+
class FooPlugin < Rucola::Plugin
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'Plugin' do
|
10
|
+
before do
|
11
|
+
@plugin = Rucola::Plugin.plugins.first
|
12
|
+
@initializer_mock = mock('Initializer')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "contains list of plugin subclasses" do
|
16
|
+
Rucola::Plugin.plugins.map { |p| p.class }.should == [FooPlugin]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should run before boot plugins" do
|
20
|
+
@plugin.expects(:before_boot)
|
21
|
+
Rucola::Plugin.before_boot
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should run after boot plugins" do
|
25
|
+
@plugin.expects(:after_boot)
|
26
|
+
Rucola::Plugin.after_boot
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should run before process plugins" do
|
30
|
+
@plugin.expects(:before_process).with(@initializer_mock)
|
31
|
+
Rucola::Plugin.before_process(@initializer_mock)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should run after process plugins" do
|
35
|
+
@plugin.expects(:after_process).with(@initializer_mock)
|
36
|
+
Rucola::Plugin.after_process(@initializer_mock)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be able to run after launch plugins" do
|
40
|
+
@plugin.expects(:after_launch)
|
41
|
+
Rucola::Plugin.after_launch
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should run after launch plugins when the app has started" do
|
45
|
+
@plugin.expects(:after_launch)
|
46
|
+
OSX::NSNotificationCenter.defaultCenter.postNotificationName_object(OSX::NSApplicationDidFinishLaunchingNotification, self)
|
47
|
+
end
|
48
|
+
end
|