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.
Files changed (49) hide show
  1. data/ChangeLog +301 -0
  2. data/History.txt +51 -0
  3. data/Manifest.txt +12 -0
  4. data/README.txt +6 -7
  5. data/TODO +13 -8
  6. data/app_generators/rucola/rucola_generator.rb +1 -1
  7. data/app_generators/rucola/templates/app/controllers/application_controller.rb +2 -2
  8. data/app_generators/rucola/templates/test/controllers/test_application_controller.rb +22 -5
  9. data/app_generators/rucola/templates/test/test_helper.rb +3 -2
  10. data/config/hoe.rb +2 -2
  11. data/lib/autotest/discover.rb +9 -0
  12. data/lib/autotest/fail.png +0 -0
  13. data/lib/autotest/growl_images.rb +39 -0
  14. data/lib/autotest/pass.png +0 -0
  15. data/lib/autotest/rucola.rb +36 -0
  16. data/lib/autotest/sound.rb +52 -0
  17. data/lib/rucola/info_plist.rb +5 -0
  18. data/lib/rucola/initializer.rb +65 -113
  19. data/lib/rucola/nib.rb +2 -2
  20. data/lib/rucola/plugin.rb +57 -0
  21. data/lib/rucola/rucola_support/initialize_hooks.rb +7 -0
  22. data/lib/rucola/rucola_support/notifications/notifications.rb +67 -27
  23. data/lib/rucola/rucola_support/rc_app.rb +9 -0
  24. data/lib/rucola/tasks/main.rake +8 -4
  25. data/lib/rucola/tasks/xcode.rake +10 -6
  26. data/lib/rucola/test_helper.rb +14 -0
  27. data/lib/rucola/version.rb +1 -1
  28. data/lib/rucola/xcode.rb +11 -6
  29. data/rucola_generators/controller/controller_generator.rb +1 -1
  30. data/rucola_generators/controller/templates/test_controller_template.rb.erb +14 -5
  31. data/rucola_generators/document_model/document_model_generator.rb +3 -3
  32. data/rucola_generators/document_model/templates/test_document_model_template.rb.erb +18 -5
  33. data/rucola_generators/rucola_plugin/USAGE +6 -0
  34. data/rucola_generators/rucola_plugin/rucola_plugin_generator.rb +63 -0
  35. data/rucola_generators/rucola_plugin/templates/init.rb.erb +25 -0
  36. data/rucola_generators/window_controller/templates/test_window_controller_template.rb.erb +21 -5
  37. data/rucola_generators/window_controller/window_controller_generator.rb +1 -1
  38. data/test/test_document_model_generator.rb +8 -2
  39. data/test/test_info_plist.rb +4 -0
  40. data/test/test_initializer.rb +80 -0
  41. data/test/test_nib.rb +9 -0
  42. data/test/test_notifications.rb +38 -19
  43. data/test/test_plugin.rb +48 -0
  44. data/test/test_rc_app.rb +5 -0
  45. data/test/test_rucola_plugin_generator.rb +65 -0
  46. data/test/test_xcode.rb +3 -3
  47. data/website/index.html +49 -7
  48. data/website/index.txt +34 -4
  49. metadata +37 -2
@@ -1,10 +1,23 @@
1
1
  require File.expand_path('../../test_helper', __FILE__)
2
2
 
3
- class Test<%= name.camel_case %> < Test::Unit::TestCase
4
-
5
- def test_<%= name.snake_case %>_initialization
6
- <%= name.snake_case %> = <%= name.camel_case %>.alloc.init
7
- assert_instance_of(<%= name.camel_case %>, <%= name.snake_case %>)
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,6 @@
1
+ Description:
2
+
3
+ Running this command will create the plugin structure and an init.rb in vendor/plugins/<name>.
4
+
5
+ You can specify -r if you prefer rspec to test/unit or test/spec. This will create a spec dir instead of a test dir.
6
+
@@ -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
- class Test<%= name.camel_case %>Controller < Test::Unit::TestCase
4
-
5
- def test_<%= name.snake_case %>_controller_initialization
6
- <%= name.snake_case %>_controller = <%= name.camel_case %>Controller.alloc.init
7
- assert_instance_of(<%= name.camel_case %>Controller, <%= name.snake_case %>_controller)
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
@@ -48,7 +48,7 @@ class WindowControllerGenerator < RubiGen::Base
48
48
  protected
49
49
  def banner
50
50
  <<-EOS
51
- Creates a ...
51
+ Creates a window controller that inherits from NSWindowController.
52
52
 
53
53
  USAGE: #{$0} #{spec.name} name"
54
54
  EOS
@@ -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 test_generator_without_options
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(:[]).with('CFBundleDocumentTypes').returns(doc_types)
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)
@@ -28,4 +28,8 @@ describe "Info" do
28
28
  @info_plist.data.expects(:writeToFile_atomically).with(@path, true)
29
29
  @info_plist.save
30
30
  end
31
+
32
+ it "should be able to return the name of the application" do
33
+ @info_plist.app_name.should == 'MyApp'
34
+ end
31
35
  end
@@ -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
@@ -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)
@@ -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
- BarNotifiable.notify_on 'NSApplicationDidFinishLaunchingNotification' do |notification|
32
+ FooNotifiable.notify_on 'NSApplicationDidFinishLaunchingNotification' do |notification|
30
33
  app_finished_launching
31
34
  end
32
35
 
33
- BarNotifiable.alloc.init.expects(:app_finished_launching)
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
- BazNotifiable.notify_on :application_did_become_active do |notification|
42
+ FooNotifiable.notify_on :application_did_become_active do |notification|
39
43
  app_did_become_active
40
44
  end
41
45
 
42
- BazNotifiable.alloc.init.expects(:app_did_become_active)
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
- FuNotifiable.notification_prefix :win => :window
52
+ FooNotifiable.notification_prefix :win => :window
52
53
 
53
- FuNotifiable.notify_on :win_did_become_key do |notification|
54
+ FooNotifiable.notify_on :win_did_become_key do |notification|
54
55
  window_did_become_key
55
56
  end
56
-
57
- FuNotifiable.alloc.init.expects(:window_did_become_key)
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
- KungNotifiable.notify_on :app_will_terminate do |notification|
64
+ FooNotifiable.notify_on :app_will_terminate do |notification|
63
65
  app_will_terminate_called!
64
66
  end
65
67
 
66
- KungNotifiable.alloc.init.expects(:app_will_terminate_called!)
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
@@ -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