kicker 2.0.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.
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Array#take_and_map" do
4
+ before do
5
+ @array = %w{ foo bar baz }
6
+ end
7
+
8
+ it "should remove elements from the array for which the block evaluates to true" do
9
+ @array.take_and_map { |x| x =~ /^ba/ }
10
+ @array.should == %w{ foo }
11
+ end
12
+
13
+ it "should return a new array of the return values of each block call that evaluates to true" do
14
+ @array.take_and_map { |x| $1 if x =~ /^ba(\w)/ }.should == %w{ r z }
15
+ end
16
+
17
+ it "should flatten and compact the result array" do
18
+ @array.take_and_map do |x|
19
+ x =~ /^ba/ ? %w{ f o o } : [nil]
20
+ end.should == %w{ f o o f o o }
21
+ end
22
+
23
+ it "should not flatten and compact the result array if specified" do
24
+ @array.take_and_map(false) do |x|
25
+ x =~ /^ba/ ? %w{ f o o } : [nil]
26
+ end.should == [[nil], %w{ f o o }, %w{ f o o }]
27
+ end
28
+ end
@@ -0,0 +1,100 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Kicker, when a change occurs" do
4
+ before do
5
+ remove_tmp_files!
6
+
7
+ Kicker.any_instance.stubs(:last_command_succeeded?).returns(true)
8
+ Kicker.any_instance.stubs(:log)
9
+ @kicker = Kicker.new({})
10
+ end
11
+
12
+ it "should store the current time as when the last change occurred" do
13
+ now = Time.now
14
+ Time.stubs(:now).returns(now)
15
+
16
+ @kicker.send(:finished_processing!)
17
+ @kicker.last_event_processed_at.should.be now
18
+ end
19
+
20
+ it "should return an array of files that have changed since the last event" do
21
+ file1 = touch('1')
22
+ file2 = touch('2')
23
+ file3 = touch('3')
24
+ file4 = touch('4')
25
+ @kicker.send(:finished_processing!)
26
+
27
+ events = [event(file1, file2), event(file3, file4)]
28
+
29
+ @kicker.send(:changed_files, events).should == []
30
+ @kicker.send(:finished_processing!)
31
+
32
+ sleep(1)
33
+ touch('2')
34
+
35
+ @kicker.send(:changed_files, events).should == [file2]
36
+ @kicker.send(:finished_processing!)
37
+
38
+ sleep(1)
39
+ touch('1')
40
+ touch('3')
41
+
42
+ @kicker.send(:changed_files, events).should == [file1, file3]
43
+ end
44
+
45
+ it "should not break when determining changed files from events with missing files" do
46
+ file1 = touch('1')
47
+ file2 = touch('2')
48
+ @kicker.send(:finished_processing!)
49
+ sleep(1)
50
+ touch('2')
51
+
52
+ events = [event(file1, file2), event('/does/not/exist')]
53
+ @kicker.send(:changed_files, events).should == [file2]
54
+ end
55
+
56
+ it "should return relative file paths if the path is relative to the current work dir" do
57
+ sleep(1)
58
+ file = touch('1')
59
+
60
+ Dir.stubs(:pwd).returns('/tmp')
61
+ @kicker.send(:changed_files, [event(file)]).should == [File.basename(file)]
62
+ end
63
+
64
+ it "should call the full_chain with all changed files" do
65
+ files = %w{ /file/1 /file/2 }
66
+ events = [event('/file/1'), event('/file/2')]
67
+
68
+ @kicker.expects(:changed_files).with(events).returns(files)
69
+ @kicker.full_chain.expects(:call).with(files)
70
+ @kicker.expects(:finished_processing!)
71
+
72
+ @kicker.send(:process, events)
73
+ end
74
+
75
+ it "should not call the full_chain if there were no changed files" do
76
+ @kicker.stubs(:changed_files).returns([])
77
+ @kicker.full_chain.expects(:call).never
78
+ @kicker.expects(:finished_processing!).never
79
+
80
+ @kicker.send(:process, [event()])
81
+ end
82
+
83
+ private
84
+
85
+ def touch(file)
86
+ file = "/tmp/kicker_test_tmp_#{file}"
87
+ `touch #{file}`
88
+ file
89
+ end
90
+
91
+ def event(*files)
92
+ event = stub('FSEvent')
93
+ event.stubs(:path).returns('/tmp')
94
+ event
95
+ end
96
+
97
+ def remove_tmp_files!
98
+ Dir.glob("/tmp/kicker_test_tmp_*").each { |f| File.delete(f) }
99
+ end
100
+ end
@@ -0,0 +1,2 @@
1
+ $FROM_RELOADED_FILE ||= 0
2
+ $FROM_RELOADED_FILE += 1
@@ -0,0 +1,165 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module ReloadDotKick; end
4
+
5
+ describe "Kicker" do
6
+ before do
7
+ Kicker.any_instance.stubs(:start)
8
+ end
9
+
10
+ it "should add kicker/recipes to the load path" do
11
+ $:.should.include File.expand_path('../../lib/kicker/recipes', __FILE__)
12
+ end
13
+
14
+ if File.exist?(File.expand_path('~/.kick'))
15
+ it "should add ~/.kick to the load path" do
16
+ $:.should.include File.expand_path('~/.kick')
17
+ end
18
+ else
19
+ puts "[!] ~/.kick does not exist, skipping an example."
20
+ end
21
+
22
+ it "should return the default paths to watch" do
23
+ Kicker.paths.should == %w{ . }
24
+ end
25
+
26
+ it "should check if a .kick file exists and if so load it and add the ReloadDotKick handler" do
27
+ File.expects(:exist?).with('.kick').returns(true)
28
+ Kicker.expects(:require).with('dot_kick')
29
+ ReloadDotKick.expects(:save_state)
30
+ Kicker.expects(:load).with('.kick')
31
+ Kicker.run
32
+ end
33
+
34
+ it "should check if a recipe exists and load it" do
35
+ Kicker.stubs(:load_dot_kick)
36
+
37
+ Kicker.expects(:require).with('rails')
38
+ Kicker.expects(:require).with('ignore')
39
+ Kicker.run(%w{ -r rails -r ignore })
40
+ end
41
+
42
+ it "should raise if a recipe does not exist" do
43
+ Kicker.expects(:require).never
44
+ lambda { Kicker.run(%w{ -r foobar -r rails }) }.should.raise
45
+ end
46
+ end
47
+
48
+ describe "Kicker, when initializing" do
49
+ before do
50
+ @now = Time.now
51
+ Time.stubs(:now).returns(@now)
52
+
53
+ @kicker = Kicker.new(:paths => %w{ /some/dir a/relative/path })
54
+ end
55
+
56
+ it "should return the extended paths to watch" do
57
+ @kicker.paths.should == ['/some/dir', File.expand_path('a/relative/path')]
58
+ end
59
+
60
+ it "should have assigned the current time to last_event_processed_at" do
61
+ @kicker.last_event_processed_at.should == @now
62
+ end
63
+
64
+ it "should use the default paths if no paths were given" do
65
+ Kicker.new({}).paths.should == [File.expand_path('.')]
66
+ end
67
+
68
+ it "should use the default FSEvents latency if none was given" do
69
+ @kicker.latency.should == 1
70
+ end
71
+
72
+ it "should use the given FSEvents latency if one was given" do
73
+ Kicker.new(:latency => 3.5).latency.should == 3.5
74
+ end
75
+ end
76
+
77
+ describe "Kicker, when starting" do
78
+ before do
79
+ @kicker = Kicker.new(:paths => %w{ /some/file.rb })
80
+ @kicker.stubs(:log)
81
+ Rucola::FSEvents.stubs(:start_watching)
82
+ OSX.stubs(:CFRunLoopRun)
83
+ end
84
+
85
+ it "should show the usage banner and exit when there are no callbacks defined at all" do
86
+ @kicker.stubs(:validate_paths_exist!)
87
+ Kicker.stubs(:process_chain).returns([])
88
+ Kicker.stubs(:pre_process_chain).returns([])
89
+
90
+ Kicker::OPTION_PARSER_CALLBACK.stubs(:call).returns(mock('OptionParser', :help => 'help'))
91
+ @kicker.expects(:puts).with("help")
92
+ @kicker.expects(:exit)
93
+
94
+ @kicker.start
95
+ end
96
+
97
+ it "should warn the user and exit if any of the given paths doesn't exist" do
98
+ @kicker.stubs(:validate_paths_and_command!)
99
+
100
+ @kicker.expects(:puts).with("The given path `/some/file.rb' does not exist")
101
+ @kicker.expects(:exit).with(1)
102
+
103
+ @kicker.start
104
+ end
105
+
106
+ it "should start a FSEvents stream with the assigned latency" do
107
+ @kicker.stubs(:validate_options!)
108
+
109
+ Rucola::FSEvents.expects(:start_watching).with(['/some'], :latency => @kicker.latency)
110
+ @kicker.start
111
+ end
112
+
113
+ it "should start a FSEvents stream which watches all paths, but the dirnames of paths if they're files" do
114
+ @kicker.stubs(:validate_options!)
115
+ File.stubs(:directory?).with('/some/file.rb').returns(false)
116
+
117
+ Rucola::FSEvents.expects(:start_watching).with(['/some'], :latency => @kicker.latency)
118
+ @kicker.start
119
+ end
120
+
121
+ it "should start a FSEvents stream with a block which calls #process with any generated events" do
122
+ @kicker.stubs(:validate_options!)
123
+
124
+ Rucola::FSEvents.expects(:start_watching).yields(['event'])
125
+ @kicker.expects(:process).with(['event'])
126
+
127
+ @kicker.start
128
+ end
129
+
130
+ it "should setup a signal handler for `INT' which stops the FSEvents stream and exits" do
131
+ @kicker.stubs(:validate_options!)
132
+
133
+ watch_dog = stub('Rucola::FSEvents')
134
+ Rucola::FSEvents.stubs(:start_watching).returns(watch_dog)
135
+
136
+ @kicker.expects(:trap).with('INT').yields
137
+ watch_dog.expects(:stop)
138
+ @kicker.expects(:exit)
139
+
140
+ @kicker.start
141
+ end
142
+
143
+ it "should start a CFRunLoop" do
144
+ @kicker.stubs(:validate_options!)
145
+
146
+ OSX.expects(:CFRunLoopRun)
147
+ @kicker.start
148
+ end
149
+
150
+ it "should register with growl if growl should be used" do
151
+ @kicker.stubs(:validate_options!)
152
+ Kicker.use_growl = true
153
+
154
+ Growl::Notifier.sharedInstance.expects(:register).with('Kicker', Kicker::GROWL_NOTIFICATIONS.values)
155
+ @kicker.start
156
+ end
157
+
158
+ it "should _not_ register with growl if growl should not be used" do
159
+ @kicker.stubs(:validate_options!)
160
+ Kicker.use_growl = false
161
+
162
+ Growl::Notifier.sharedInstance.expects(:register).never
163
+ @kicker.start
164
+ end
165
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Kicker.parse_options" do
4
+ it "should parse the paths" do
5
+ Kicker.parse_options([])[:paths].should.be nil
6
+
7
+ Kicker.parse_options(%w{ /some/file.rb })[:paths].should == %w{ /some/file.rb }
8
+ Kicker.parse_options(%w{ /some/file.rb /a/dir /and/some/other/file.rb })[:paths].should ==
9
+ %w{ /some/file.rb /a/dir /and/some/other/file.rb }
10
+ end
11
+
12
+ it "should parse if growl shouldn't be used" do
13
+ Kicker.parse_options([])[:growl].should == true
14
+ Kicker.parse_options(%w{ --no-growl })[:growl].should == false
15
+ end
16
+
17
+ it "should parse the Growl command to use when the user clicks the Growl succeeded message" do
18
+ Kicker.parse_options(%w{ --growl-command ls })[:growl_command].should == 'ls'
19
+ end
20
+
21
+ it "should parse the latency to pass to FSEvents" do
22
+ Kicker.parse_options(%w{ -l 2.5 })[:latency].should == 2.5
23
+ Kicker.parse_options(%w{ --latency 3.5 })[:latency].should == 3.5
24
+ end
25
+
26
+ it "should parse recipe requires" do
27
+ Kicker.parse_options(%w{ -r rails -r jstest })[:recipes].should == %w{ rails jstest }
28
+ Kicker.parse_options(%w{ --recipe rails --recipe jstest })[:recipes].should == %w{ rails jstest }
29
+ end
30
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ describe "Kicker, concerning the default `could not handle file' callback" do
4
+ it "should log that it could not handle the given files" do
5
+ Kicker::Utils.expects(:log).with('')
6
+ Kicker::Utils.expects(:log).with("Could not handle: /file/1, /file/2")
7
+ Kicker::Utils.expects(:log).with('')
8
+
9
+ Kicker.post_process_chain.last.call(%w{ /file/1 /file/2 })
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ before = Kicker.process_chain.dup
4
+ require 'kicker/recipes/dot_kick'
5
+ DOT_KICK = (Kicker.process_chain - before).first
6
+
7
+ describe "The .kick handler" do
8
+ it "should reset $LOADED_FEATURES and callback chains to state before loading .kick and reload .kick" do
9
+ ReloadDotKick.save_state
10
+
11
+ features_before_dot_kick = $LOADED_FEATURES.dup
12
+ chains_before_dot_kick = Kicker.full_chain.map { |c| c.dup }
13
+
14
+ ReloadDotKick.expects(:load).with('.kick').twice
15
+
16
+ 2.times do
17
+ require File.expand_path('../../fixtures/a_file_thats_reloaded', __FILE__)
18
+ process {}
19
+ DOT_KICK.call(%w{ .kick })
20
+ end
21
+
22
+ $FROM_RELOADED_FILE.should == 2
23
+ $LOADED_FEATURES.should == features_before_dot_kick
24
+ Kicker.full_chain.should == chains_before_dot_kick
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ describe "Kicker, concerning the `execute a command-line' callback" do
4
+ it "should parse the command and add the callback" do
5
+ before = Kicker.pre_process_chain.length
6
+
7
+ Kicker.parse_options(%w{ -e ls })
8
+ Kicker.pre_process_chain.length.should == before + 1
9
+
10
+ Kicker.parse_options(%w{ --execute ls })
11
+ Kicker.pre_process_chain.length.should == before + 2
12
+ end
13
+
14
+ it "should call execute with the given command" do
15
+ Kicker.parse_options(%w{ -e ls })
16
+
17
+ callback = Kicker.pre_process_chain.last
18
+ callback.should.be.instance_of Proc
19
+
20
+ Kicker::Utils.expects(:execute).with('sh -c "ls"')
21
+
22
+ callback.call(%w{ /file/1 /file/2 }).should.not.be.instance_of Array
23
+ end
24
+
25
+ it "should clear the files array to halt the chain" do
26
+ Kicker::Utils.stubs(:execute)
27
+
28
+ files = %w{ /file/1 /file/2 }
29
+ Kicker.pre_process_chain.last.call(files)
30
+ files.should.be.empty
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ before = Kicker.pre_process_chain.dup
4
+ require 'kicker/recipes/ignore'
5
+ IGNORE = (Kicker.pre_process_chain - before).first
6
+
7
+ describe "The Ignore handler" do
8
+ it "should remove files that match the given regexp" do
9
+ ignore(/^fo{2}bar/)
10
+
11
+ files = %w{ Rakefile foobar foobarbaz }
12
+ IGNORE.call(files)
13
+ files.should == %w{ Rakefile }
14
+ end
15
+
16
+ it "should remove files that match the given string" do
17
+ ignore('bazbla')
18
+
19
+ files = %w{ Rakefile bazbla bazblabla }
20
+ IGNORE.call(files)
21
+ files.should == %w{ Rakefile bazblabla }
22
+ end
23
+
24
+ it "should ignore a few file types by default" do
25
+ files = %w{ Rakefile foo/bar/dev.log .svn/foo svn-commit.tmp .git/foo tmp }
26
+ IGNORE.call(files)
27
+ files.should == %w{ Rakefile }
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ before = Kicker.process_chain.dup
4
+ require 'kicker/recipes/jstest'
5
+ JSTEST = (Kicker.process_chain - before).first
6
+
7
+ describe "The HeadlessSquirrel handler" do
8
+ before do
9
+ @files = %w{ Rakefile }
10
+ end
11
+
12
+ it "should match any test case files" do
13
+ @files += %w{ test/javascripts/ui_test.html test/javascripts/admin_test.js }
14
+
15
+ Kicker::Utils.expects(:execute).
16
+ with("jstest test/javascripts/ui_test.html test/javascripts/admin_test.html")
17
+
18
+ JSTEST.call(@files)
19
+ @files.should == %w{ Rakefile }
20
+ end
21
+
22
+ it "should map public/javascripts libs to test/javascripts" do
23
+ @files += %w{ public/javascripts/ui.js public/javascripts/admin.js }
24
+
25
+ Kicker::Utils.expects(:execute).
26
+ with("jstest test/javascripts/ui_test.html test/javascripts/admin_test.html")
27
+
28
+ JSTEST.call(@files)
29
+ @files.should == %w{ Rakefile }
30
+ end
31
+ end