ghostbuster 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -50,4 +50,20 @@ Look inside `ghost` to see some examples of what actual tests would look like. L
50
50
 
51
51
  ~~~~
52
52
 
53
- To use this within rake, just put `require 'ghostbuster/install_rake'` in your Rakefile.
53
+ To use this within rake, just put `require 'ghostbuster/install_rake'` in your Rakefile.
54
+
55
+ ## Assertions
56
+
57
+ Assertions are run in order, and only one assertion at a time can run. An assertion will have at most one second to complete. If you want to change the total amount of time an assertion will take, you can supply that time.
58
+
59
+ ~~~~
60
+ @body.assertFirst 'p', total: 3, (p) -> # this asserts the first paragraph's inner text
61
+ ~~~~
62
+
63
+ The available assertions are:
64
+
65
+ * _assertFirst_ : This asserts for the first matching DOM element
66
+ * _assertAll_ : This asserts for the each matching DOM element
67
+ * _assertLocation_ : This asserts the current browser location
68
+
69
+ The closures passed for matching have access to the real DOM node, however, they do not have any access to the outside context. They must return true if the assertion is passed, anything else will be interpreted as failure.
data/ghost/config.ru CHANGED
@@ -9,6 +9,10 @@ class App < Sinatra::Base
9
9
  get "/form" do
10
10
  erb :form
11
11
  end
12
+
13
+ get "/slow" do
14
+ erb :slow
15
+ end
12
16
  end
13
17
 
14
18
  run App
@@ -5,4 +5,17 @@ phantom.test.add "Simple form", ->
5
5
  @succeed()
6
6
 
7
7
  phantom.test.addPending "Form should do more things", ->
8
- console.log "some thing here.."
8
+ console.log "some thing here.."
9
+
10
+ phantom.test.add "Simple form with wait", ->
11
+ @get '/form', ->
12
+ @wait 1, ->
13
+ @succeed()
14
+
15
+ phantom.test.add "Slow form", ->
16
+ @get '/slow', ->
17
+ @body.input "#in", "this is my input"
18
+ @body.click "#btn"
19
+ @body.assertFirst '#out', total: 3, (out) ->
20
+ out.innerHTML == 'this is my input'
21
+ @succeed()
@@ -0,0 +1,12 @@
1
+ <html>
2
+ <head>
3
+ <title>This is my index</title>
4
+ </head>
5
+ <body>
6
+ <form>
7
+ <input type="text" id="in">
8
+ <input type="button" id="btn" onclick="setTimeout( function() { document.getElementById('out').innerHTML = document.getElementById('in').value;}, 2000);">
9
+ </form>
10
+ <p id="out"></p>
11
+ </body>
12
+ </html>
@@ -3,12 +3,14 @@ class Test
3
3
  @page = new WebPage()
4
4
  @page.onConsoleMessage = (msg) ->
5
5
  console.log "PAGE CONSOLE: #{msg}"
6
- testName = @name
7
- @page.onAlert = (msg) =>
8
- @runner.lastErrors[testName] = msg
6
+ @page.onAlert = (msg) => @setLastError(msg)
9
7
  @lastError = null
10
8
  @assertions = []
11
9
  @seenCallbacks = []
10
+ getLastError: -> @runner.lastErrors[@name]
11
+ resetLastError: -> delete @runner.lastErrors[@name]
12
+ setLastError: (error) ->
13
+ @runner.lastErrors[@name] = error
12
14
  waitForAssertions: (whenDone) ->
13
15
  if @assertions.length == 0
14
16
  whenDone.call(this)
@@ -24,7 +26,7 @@ class Test
24
26
  test = this
25
27
  loadedCallback = (status) ->
26
28
  return if test.seenCallbacks.indexOf(getCallback) != -1
27
- test.seenCallbacks.push getCallback #traversing links causes this to get re-fired.
29
+ test.seenCallbacks.push getCallback # traversing links causes this to get re-fired.
28
30
  switch status
29
31
  when 'success'
30
32
  test.body = new Body(test)
@@ -37,13 +39,18 @@ class Test
37
39
  @callback(true)
38
40
  fail: (msg) ->
39
41
  @callback(false, msg)
40
- assert: (valueFetcher) ->
41
- @assertions.push(new Assertion(this, valueFetcher))
42
+ assert: (opts, valueFetcher) ->
43
+ @assertions.push(new Assertion(this, opts, valueFetcher))
42
44
  @assertions[0].start() if @assertions.length == 1
45
+ wait: (time, callback) ->
46
+ test = this
47
+ setTimeout (-> callback.call(test)), time * 1000
43
48
 
44
49
  class Assertion
45
- constructor: (@test, @fetcher) ->
50
+ constructor: (@test, @opts, @fetcher) ->
46
51
  @count = 0
52
+ @totalTime = if @opts['total'] then @opts['total'] * 1000 else 1000
53
+ @everyTime = if @opts['every'] then @opts['every'] else 75
47
54
  start: ->
48
55
  test = @test
49
56
  assertion = this
@@ -51,21 +58,18 @@ class Assertion
51
58
  assertion.start()
52
59
  if @count == 0
53
60
  fatalCallback = ->
54
- test.fail(test.lastError || "This assertion failed to complete.")
55
- @fatal = setTimeout(fatalCallback, 1000)
61
+ test.fail(test.getLastError() || "This assertion failed to complete.")
62
+ @fatal = setTimeout(fatalCallback, assertion.totalTime)
56
63
  @fetcher.call test, (val) ->
57
64
  assertion.count++
58
65
  if val == true
59
- delete test.runner.lastErrors[test.name];
66
+ test.resetLastError()
60
67
  test.assertions.splice(test.assertions.indexOf(assertion), 1)
61
68
  clearTimeout assertion.fatal
62
69
  if test.assertions.length > 0
63
70
  test.assertions[0].start()
64
- else if assertion.count > 10
65
- clearTimeout assertion.fatal
66
- test.fail(test.lastError)
67
71
  else
68
- setTimeout(failedCallback, 75)
72
+ setTimeout(failedCallback, test.everyTime)
69
73
 
70
74
  class Body
71
75
  constructor: (@test) ->
@@ -96,11 +100,12 @@ class Body
96
100
  "
97
101
  @test.page.evaluate(fn)
98
102
 
99
- assertLocation: (path) ->
103
+ assertLocation: (path, opts) ->
104
+ opts ||= {}
100
105
  test = @test
101
106
  location = @test.runner.normalizePath(path)
102
- @test.assert (withValue) ->
103
- alerter = if test.runner.lastErrors[test.name]? then "" else "alert('Assert location failed: Excepted #{location}, got '+currentLocation);"
107
+ @test.assert opts, (withValue) ->
108
+ alerter = if test.getLastError()? then "" else "alert('Assert location failed: Excepted #{location}, got '+currentLocation);"
104
109
  eval "
105
110
  var fn = function() {
106
111
  var currentLocation = window.location.href;
@@ -114,10 +119,13 @@ class Body
114
119
  "
115
120
  withValue @page.evaluate(fn)
116
121
 
117
- assertFirst: (selector, assertionCallback) ->
122
+ assertFirst: (selector, opts, assertionCallback) ->
123
+ unless assertionCallback?
124
+ assertionCallback = opts
125
+ opts = {}
118
126
  test = @test
119
- @test.assert (withValue) ->
120
- alerter = if test.runner.lastErrors[test.name]? then "" else "alert('Assert first for selector #{selector} did not meet expectations');"
127
+ @test.assert opts, (withValue) ->
128
+ alerter = if test.getLastError()? then "" else "alert('Assert first for selector #{selector} did not meet expectations');"
121
129
  eval "
122
130
  var evaluator = function() {
123
131
  try {
@@ -139,8 +147,11 @@ class Body
139
147
  "
140
148
  withValue @page.evaluate(evaluator)
141
149
 
142
- assertAll: (selector, assertionCallback) ->
143
- @test.assert (withValue) ->
150
+ assertAll: (selector, opts, assertionCallback) ->
151
+ unless assertionCallback?
152
+ assertionCallback = opts
153
+ opts = {}
154
+ @test.assert opts, (withValue) ->
144
155
  eval "
145
156
  var evaluator = function() {
146
157
  try {
@@ -172,7 +183,10 @@ class TestFile
172
183
  @lastErrors = {}
173
184
  normalizePath: (path) -> if path.match(/^http/) then path else "#{@root}#{path}"
174
185
  addPending: (name, body) -> @tests.push new PendingTest(this, name)
175
- add: (name, body) -> @tests.push new Test(this, name, body)
186
+ add: (name, body) ->
187
+ for test in @tests
188
+ throw("Identically named test already exists for name #{name} in #{@name}") if test.name == name
189
+ @tests.push new Test(this, name, body)
176
190
  run: (callback) ->
177
191
  throw "No root is defined" unless @root?
178
192
  count = 0
@@ -199,7 +213,7 @@ class TestFile
199
213
  console.log " \033[32m\u2713\033[0m #{name}"
200
214
  else if state == 'pending'
201
215
  pending++
202
- console.log " \033[33m\u2022\033[0m #{name}"
216
+ console.log " \033[33m\u25d0\033[0m #{name}"
203
217
  else
204
218
  failure++
205
219
  console.log " \033[31m\u2717\033[0m #{name}\n #{@lastErrors[name] || "There was a problem"}"
@@ -1,3 +1,3 @@
1
1
  class Ghostbuster
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
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: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Josh Hull
@@ -19,8 +19,9 @@ date: 2011-08-26 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
+ name: thin
22
23
  prerelease: false
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ requirement: &id001 !ruby/object:Gem::Requirement
24
25
  none: false
25
26
  requirements:
26
27
  - - ~>
@@ -31,12 +32,12 @@ dependencies:
31
32
  - 2
32
33
  - 11
33
34
  version: 1.2.11
34
- requirement: *id001
35
- name: thin
36
35
  type: :development
36
+ version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
38
+ name: rake
38
39
  prerelease: false
39
- version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ requirement: &id002 !ruby/object:Gem::Requirement
40
41
  none: false
41
42
  requirements:
42
43
  - - ~>
@@ -47,12 +48,12 @@ dependencies:
47
48
  - 8
48
49
  - 7
49
50
  version: 0.8.7
50
- requirement: *id002
51
- name: rake
52
51
  type: :development
52
+ version_requirements: *id002
53
53
  - !ruby/object:Gem::Dependency
54
+ name: bundler
54
55
  prerelease: false
55
- version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ requirement: &id003 !ruby/object:Gem::Requirement
56
57
  none: false
57
58
  requirements:
58
59
  - - ~>
@@ -63,12 +64,12 @@ dependencies:
63
64
  - 0
64
65
  - 14
65
66
  version: 1.0.14
66
- requirement: *id003
67
- name: bundler
68
67
  type: :development
68
+ version_requirements: *id003
69
69
  - !ruby/object:Gem::Dependency
70
+ name: sinatra
70
71
  prerelease: false
71
- version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ requirement: &id004 !ruby/object:Gem::Requirement
72
73
  none: false
73
74
  requirements:
74
75
  - - ">="
@@ -77,9 +78,8 @@ dependencies:
77
78
  segments:
78
79
  - 0
79
80
  version: "0"
80
- requirement: *id004
81
- name: sinatra
82
81
  type: :development
82
+ version_requirements: *id004
83
83
  description: Integration testing ftw.
84
84
  email:
85
85
  - joshbuddy@gmail.com
@@ -104,6 +104,7 @@ files:
104
104
  - ghost/test_ghostmore.coffee
105
105
  - ghost/views/form.erb
106
106
  - ghost/views/index.erb
107
+ - ghost/views/slow.erb
107
108
  - ghostbuster.gemspec
108
109
  - lib/ghostbuster.coffee
109
110
  - lib/ghostbuster.rb