kicker 2.0.0

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