ghostbuster 0.1.0 → 0.2.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.
- data/README.md +31 -1
- data/Rakefile +28 -1
- data/ghost/Ghostfile +4 -0
- data/lib/ghostbuster.coffee +18 -3
- data/lib/ghostbuster.rb +7 -6
- data/lib/ghostbuster/config.rb +38 -0
- data/lib/ghostbuster/rake.rb +2 -2
- data/lib/ghostbuster/runner.rb +4 -4
- data/lib/ghostbuster/version.rb +1 -1
- data/test/output +23 -0
- metadata +9 -6
data/README.md
CHANGED
@@ -8,7 +8,37 @@ To install first `gem install ghostbuster`. Once you've done that, you can run `
|
|
8
8
|
|
9
9
|
## Usage
|
10
10
|
|
11
|
-
Once installed, you can simply use `ghostbuster path/to/
|
11
|
+
Once installed, you can simply use `ghostbuster [path/to/Ghostfile]` to run your tests.
|
12
|
+
|
13
|
+
## `Ghostfile`
|
14
|
+
|
15
|
+
Your `Ghostfile` handles your configuration. To set the pattern use:
|
16
|
+
|
17
|
+
~~~~
|
18
|
+
ghost.pattern = "test_*.coffee" # this is the default
|
19
|
+
~~~~
|
20
|
+
|
21
|
+
To enable (or disable) screenshots use:
|
22
|
+
|
23
|
+
~~~~
|
24
|
+
ghost.take_screenshots! # or #do_not_takescreenshots! defaults to take_screenshots!
|
25
|
+
~~~~
|
26
|
+
|
27
|
+
To set the directory your screenshots will save to use:
|
28
|
+
|
29
|
+
~~~~
|
30
|
+
ghost.screenshot_dir = '.'
|
31
|
+
~~~~
|
32
|
+
|
33
|
+
To set the dimensions for the screenshots use:
|
34
|
+
|
35
|
+
~~~~
|
36
|
+
ghost.screenshot_dimensions 800, 2000 # x, y
|
37
|
+
~~~~
|
38
|
+
|
39
|
+
If no Ghostfile is found, it will simply use the defaults.
|
40
|
+
|
41
|
+
You should get some output that looks something like this.
|
12
42
|
|
13
43
|
~~~~
|
14
44
|
|
data/Rakefile
CHANGED
@@ -1,3 +1,30 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
$: << 'lib'
|
3
|
-
require 'ghostbuster/install_rake'
|
3
|
+
require 'ghostbuster/install_rake'
|
4
|
+
|
5
|
+
def test_output
|
6
|
+
out = `bundle exec rake test:ghostbuster`
|
7
|
+
$?.success? ? out.gsub(/server .*?\n/m, "server\n") : raise("there was a problem")
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Run tests"
|
11
|
+
task :test do
|
12
|
+
out = test_output
|
13
|
+
if File.read(File.join(File.dirname(__FILE__), 'test', 'output')) == out
|
14
|
+
puts "Everything is great!"
|
15
|
+
else
|
16
|
+
puts out
|
17
|
+
raise "Things aren't great."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Update tests"
|
22
|
+
task :'test:update' do
|
23
|
+
File.open(File.join(File.dirname(__FILE__), 'test', 'output'), 'w') {|f| f << test_output}
|
24
|
+
puts "Test output updated"
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Show output"
|
28
|
+
task :"test:output" do
|
29
|
+
puts test_output
|
30
|
+
end
|
data/ghost/Ghostfile
ADDED
data/lib/ghostbuster.coffee
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
class Test
|
2
2
|
constructor: (@runner, @name, @testBody) ->
|
3
3
|
@page = new WebPage()
|
4
|
+
if @runner.useScreenshots()
|
5
|
+
@page.viewportSize = @runner.viewportDimensions()
|
4
6
|
@page.onConsoleMessage = (msg) ->
|
5
7
|
console.log "PAGE CONSOLE: #{msg}"
|
6
8
|
@page.onAlert = (msg) => @setLastError(msg)
|
7
9
|
@lastError = null
|
8
10
|
@assertions = []
|
9
11
|
@seenCallbacks = []
|
12
|
+
@assertionIndex = 0
|
13
|
+
nameForRender: -> "#{@runner.suite.screenshot_dir}/#{@runner.nameForRender()}-#{@name.toLowerCase()}".replace(///\s///g, '_').replace(///'///g, '')
|
10
14
|
getLastError: -> @runner.lastErrors[@name]
|
11
15
|
resetLastError: -> delete @runner.lastErrors[@name]
|
12
16
|
setLastError: (error) ->
|
@@ -43,17 +47,18 @@ class Test
|
|
43
47
|
fail: (msg) ->
|
44
48
|
@callback(false, msg)
|
45
49
|
assert: (opts, valueFetcher) ->
|
46
|
-
@assertions.push(new Assertion(this, opts, valueFetcher))
|
50
|
+
@assertions.push(new Assertion(this, ++@assertionIndex, opts, valueFetcher))
|
47
51
|
@assertions[0].start() if @assertions.length == 1
|
48
52
|
wait: (time, callback) ->
|
49
53
|
test = this
|
50
54
|
setTimeout (-> callback.call(test)), time * 1000
|
51
55
|
|
52
56
|
class Assertion
|
53
|
-
constructor: (@test, @opts, @fetcher) ->
|
57
|
+
constructor: (@test, @idx, @opts, @fetcher) ->
|
54
58
|
@count = 0
|
55
59
|
@totalTime = if @opts['total'] then @opts['total'] * 1000 else 1000
|
56
60
|
@everyTime = if @opts['every'] then @opts['every'] else 75
|
61
|
+
nameForRender: -> "#{@test.nameForRender()}-#{@idx}.png"
|
57
62
|
start: ->
|
58
63
|
test = @test
|
59
64
|
assertion = this
|
@@ -69,6 +74,8 @@ class Assertion
|
|
69
74
|
test.resetLastError()
|
70
75
|
test.assertions.splice(test.assertions.indexOf(assertion), 1)
|
71
76
|
clearTimeout assertion.fatal
|
77
|
+
if test.runner.useScreenshots()
|
78
|
+
test.page.render assertion.nameForRender()
|
72
79
|
if test.assertions.length > 0
|
73
80
|
test.assertions[0].start()
|
74
81
|
else
|
@@ -180,12 +187,16 @@ class PendingTest
|
|
180
187
|
constructor: (@runner, @name) ->
|
181
188
|
run: (callback) -> callback('pending')
|
182
189
|
actuallyRun: -> false
|
190
|
+
|
183
191
|
class TestFile
|
184
192
|
constructor: (@suite, @name) ->
|
185
193
|
@tests = []
|
186
194
|
@lastErrors = {}
|
187
195
|
@befores = []
|
188
196
|
@afters = []
|
197
|
+
nameForRender: -> @name.toLowerCase()
|
198
|
+
useScreenshots: -> @suite.screenshots
|
199
|
+
viewportDimensions: -> width: @suite.screenshot_x, height: @suite.screenshot_y
|
189
200
|
normalizePath: (path) -> if path.match(/^http/) then path else "#{@root}#{path}"
|
190
201
|
addPending: (name, body) -> @tests.push new PendingTest(this, name)
|
191
202
|
before: (body) -> @befores.push(body)
|
@@ -257,7 +268,11 @@ class TestSuite
|
|
257
268
|
@failure += failure
|
258
269
|
@pending += pending
|
259
270
|
run: ->
|
260
|
-
|
271
|
+
@screenshots = @args[0] == 'true'
|
272
|
+
@screenshot_x = @args[1]
|
273
|
+
@screenshot_y = @args[2]
|
274
|
+
@screenshot_dir = @args[3]
|
275
|
+
count = 4
|
261
276
|
suite = this
|
262
277
|
runNextTest = ->
|
263
278
|
if suite.args.length == count
|
data/lib/ghostbuster.rb
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
require 'ghostbuster/version'
|
2
2
|
require 'ghostbuster/shell'
|
3
|
+
require 'ghostbuster/config'
|
3
4
|
|
4
5
|
class Ghostbuster
|
5
6
|
include Shell
|
6
7
|
autoload :Rake, 'ghostbuster/rake'
|
7
8
|
autoload :Runner, 'ghostbuster/runner'
|
8
9
|
|
9
|
-
def initialize(
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
10
|
+
def initialize(path)
|
11
|
+
@path = File.exist?(path) ? path : '.'
|
12
|
+
@dir = File.directory?(@path) ? @path : File.basename(@path)
|
13
|
+
@file = File.directory?(@dir) ? File.join(@dir, 'Ghostfile') : @dir
|
13
14
|
@ghost_lib = File.expand_path(File.join(File.dirname(__FILE__), "ghostbuster.coffee"))
|
14
15
|
@phantom_bin = File.join(ENV['HOME'], '.ghostbuster', 'phantomjs')
|
16
|
+
@config = Config.new(@file)
|
15
17
|
STDOUT.sync = true
|
16
18
|
end
|
17
19
|
|
18
20
|
def run
|
19
|
-
files = Array(@paths).map{|path| Dir[path].to_a}.flatten.map{|f| File.expand_path(f)}
|
20
21
|
status = 1
|
21
22
|
Dir.chdir(@dir) do
|
22
23
|
spinner "Starting server" do
|
@@ -24,7 +25,7 @@ class Ghostbuster
|
|
24
25
|
sleep 2
|
25
26
|
end
|
26
27
|
begin
|
27
|
-
_, status = Process.waitpid2 fork { exec("#{@phantom_bin} #{@ghost_lib} #{
|
28
|
+
_, status = Process.waitpid2 fork { exec("#{@phantom_bin} #{@ghost_lib} #{@config.screenshots?} #{@config.screenshot_x} #{@config.screenshot_y} #{File.expand_path(@config.screenshot_dir)} #{Dir[@config.pattern].to_a.join(' ')}") }
|
28
29
|
ensure
|
29
30
|
spinner "Stopping server" do
|
30
31
|
sh "./stop.sh"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Ghostbuster
|
2
|
+
class Config
|
3
|
+
|
4
|
+
attr_accessor :pattern, :screenshot_dir
|
5
|
+
attr_reader :screenshot_x, :screenshot_y
|
6
|
+
def initialize(path_to_file = nil)
|
7
|
+
@config_file = path_to_file || './Ghostfile'
|
8
|
+
@screenshot_x, @screenshot_y = 800, 2000
|
9
|
+
@pattern = "./test_*.coffee"
|
10
|
+
@screenshot_dir = "."
|
11
|
+
@screenshots = true
|
12
|
+
if File.exist?(@config_file)
|
13
|
+
instance_eval File.read(@config_file), @config_file, 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def ghost
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def screenshot_dimensions(x, y)
|
22
|
+
@screenshot_x, @screenshot_y = x, y
|
23
|
+
end
|
24
|
+
|
25
|
+
def do_not_take_screenshots!
|
26
|
+
@screenshots = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def take_screenshots!
|
30
|
+
@screenshots = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def screenshots?
|
34
|
+
@screenshots
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/lib/ghostbuster/rake.rb
CHANGED
@@ -7,11 +7,11 @@ class Ghostbuster
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
def self.include_rake_tasks(opts = {})
|
10
|
+
opts[:path] ||= './ghost'
|
10
11
|
opts[:task_name] ||= :"test:ghostbuster"
|
11
|
-
opts[:file_pattern] ||= "ghost/test_*.{coffee,js}"
|
12
12
|
desc "Run ghostbuster tasks"
|
13
13
|
task opts[:task_name] do
|
14
|
-
Ghostbuster.new(opts[:
|
14
|
+
Ghostbuster.new(opts[:path]).run
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/ghostbuster/runner.rb
CHANGED
@@ -5,12 +5,12 @@ class Ghostbuster
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def run
|
8
|
-
if @args.size ==
|
9
|
-
puts "ghostbuster
|
8
|
+
if @args.size == 1 && @args.first == /^--?[\?h](|elp)$/i or @args.size > 1
|
9
|
+
puts "ghostbuster [path/to/Ghostfile]"
|
10
10
|
puts " Version #{VERSION}"
|
11
|
-
exit(
|
11
|
+
exit(0)
|
12
12
|
else
|
13
|
-
Ghostbuster.new(@args).run
|
13
|
+
Ghostbuster.new(@args.first).run
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
data/lib/ghostbuster/version.rb
CHANGED
data/test/output
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
(in /Users/joshbuddy/Development/ghostbuster)
|
2
|
+
Starting server
|
3
|
+
GhostBuster
|
4
|
+
For [1mtest_ghost.coffee[0m
|
5
|
+
[32m✓[0m Simple index
|
6
|
+
[32m✓[0m Form input
|
7
|
+
[32m✓[0m Link traversal
|
8
|
+
[31m✗[0m Bad link traversal
|
9
|
+
Assert location failed: Excepted http://127.0.0.1:4567/not-correct, got http://127.0.0.1:4567/
|
10
|
+
[31m✗[0m Form input not equal
|
11
|
+
Assert first for selector #out did not meet expectations
|
12
|
+
|
13
|
+
For [1mtest_ghostmore.coffee[0m
|
14
|
+
[32m✓[0m Simple form
|
15
|
+
[33m◐[0m Form should do more things
|
16
|
+
[32m✓[0m Simple form with wait
|
17
|
+
[32m✓[0m Slow form
|
18
|
+
[32m✓[0m Before block var
|
19
|
+
[31m✗[0m This test will explode!
|
20
|
+
I hate you!
|
21
|
+
|
22
|
+
7 success, 3 failure, 1 pending
|
23
|
+
Stopping server
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ghostbuster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Josh Hull
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-08-
|
18
|
+
date: 2011-08-30 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- Rakefile
|
98
98
|
- bin/ghostbuster
|
99
99
|
- bin/setup-ghostbuster
|
100
|
+
- ghost/Ghostfile
|
100
101
|
- ghost/config.ru
|
101
102
|
- ghost/start.sh
|
102
103
|
- ghost/stop.sh
|
@@ -108,12 +109,14 @@ files:
|
|
108
109
|
- ghostbuster.gemspec
|
109
110
|
- lib/ghostbuster.coffee
|
110
111
|
- lib/ghostbuster.rb
|
112
|
+
- lib/ghostbuster/config.rb
|
111
113
|
- lib/ghostbuster/install_rake.rb
|
112
114
|
- lib/ghostbuster/rake.rb
|
113
115
|
- lib/ghostbuster/runner.rb
|
114
116
|
- lib/ghostbuster/shell.rb
|
115
117
|
- lib/ghostbuster/version.rb
|
116
118
|
- log/thin.log
|
119
|
+
- test/output
|
117
120
|
has_rdoc: true
|
118
121
|
homepage: https://github.com/joshbuddy/ghostbuster
|
119
122
|
licenses: []
|
@@ -148,5 +151,5 @@ rubygems_version: 1.6.2
|
|
148
151
|
signing_key:
|
149
152
|
specification_version: 3
|
150
153
|
summary: Integration testing ftw
|
151
|
-
test_files:
|
152
|
-
|
154
|
+
test_files:
|
155
|
+
- test/output
|