rucola 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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