more fixes, plus start messing around with capybara-like way to interact with jquery elements for testing
This commit is contained in:
parent
81673543fe
commit
01f2b2a0e3
3
Gemfile
3
Gemfile
@ -7,3 +7,6 @@ gem 'guard', '~> 0.8.0'
|
|||||||
gem 'jasmine-headless-webkit', :path => '../jasmine-headless-webkit'
|
gem 'jasmine-headless-webkit', :path => '../jasmine-headless-webkit'
|
||||||
gem 'guard-jasmine-headless-webkit', :path => '../guard-jasmine-headless-webkit'
|
gem 'guard-jasmine-headless-webkit', :path => '../guard-jasmine-headless-webkit'
|
||||||
gem 'rb-fsevent'
|
gem 'rb-fsevent'
|
||||||
|
gem 'jquery-rails'
|
||||||
|
gem 'rack', '~> 1.2.0'
|
||||||
|
gem 'sprockets', '~> 2.0.0'
|
||||||
|
29
lib/assets/javascripts/cabiai.js.coffee
Normal file
29
lib/assets/javascripts/cabiai.js.coffee
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#= require jquery
|
||||||
|
#
|
||||||
|
this.Cabiai =
|
||||||
|
wrapException: (view, message) ->
|
||||||
|
throw new Error("#{message}\nin: #{$(view).html()}")
|
||||||
|
|
||||||
|
Actions:
|
||||||
|
_view: -> Cabiai.viewSource.apply(this)
|
||||||
|
|
||||||
|
clickOn: (text) ->
|
||||||
|
found = false
|
||||||
|
|
||||||
|
$('button', @_view()).each (index, element) =>
|
||||||
|
if !found and $(element).text() == text
|
||||||
|
$(element).click()
|
||||||
|
|
||||||
|
found = true
|
||||||
|
|
||||||
|
Cabiai.wrapException(@_view(), "Button not found: #{text}") if !found
|
||||||
|
|
||||||
|
within: (selector, callback) ->
|
||||||
|
preservedView = @_view
|
||||||
|
view = $(selector, @_view())
|
||||||
|
@_view = -> view
|
||||||
|
|
||||||
|
callback.apply(this)
|
||||||
|
|
||||||
|
@_view = preservedView
|
||||||
|
|
@ -1,17 +1,18 @@
|
|||||||
class jasmine.GWT.Background
|
class jasmine.GWT.Background
|
||||||
constructor: (code) ->
|
constructor: (@code) ->
|
||||||
@statements = []
|
@statements = []
|
||||||
|
|
||||||
|
run: =>
|
||||||
jasmine.GWT.currentScenario_ = this
|
jasmine.GWT.currentScenario_ = this
|
||||||
|
|
||||||
code.apply(this)
|
@code.apply(this)
|
||||||
|
|
||||||
jasmine.GWT.currentScenario_ = null
|
jasmine.GWT.currentScenario_ = null
|
||||||
|
|
||||||
Given: (name, code) ->
|
Given: (name, code) => this.Step('Given', name, code)
|
||||||
@statements.push([ 'Given', name, code ])
|
When: (name, code) => this.Step('When', name, code)
|
||||||
When: (name, code) ->
|
Then: (name, code) => this.Step('Then', name, code)
|
||||||
@statements.push([ 'When', name, code ])
|
|
||||||
Then: (name, code) ->
|
Step: (type, name, code) =>
|
||||||
@statements.push([ 'Then', name, code ])
|
@statements.push([ type, name, code ])
|
||||||
|
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
class jasmine.GWT.Feature
|
class jasmine.GWT.Feature
|
||||||
constructor: (@name, code) ->
|
constructor: (@name, @code) ->
|
||||||
|
|
||||||
|
run: =>
|
||||||
jasmine.GWT.currentFeature_ = this
|
jasmine.GWT.currentFeature_ = this
|
||||||
|
|
||||||
@background = null
|
@background = null
|
||||||
code.apply(this)
|
@code.apply(this)
|
||||||
|
|
||||||
jasmine.GWT.currentFeature_ = null
|
jasmine.GWT.currentFeature_ = null
|
||||||
|
|
||||||
Scenario: (name, code) ->
|
Scenario: (name, code) ->
|
||||||
new jasmine.GWT.Scenario(name, code, this)
|
scenario = new jasmine.GWT.Scenario(name, code, this)
|
||||||
|
scenario.run()
|
||||||
|
|
||||||
Background: (code) ->
|
Background: (code) ->
|
||||||
@background = new jasmine.GWT.Background(code)
|
@background = new jasmine.GWT.Background(code)
|
||||||
|
@background.run()
|
||||||
|
|
||||||
|
@ -1,106 +1,115 @@
|
|||||||
#= require jasmine/GWT/Background
|
#= require jasmine/GWT/Background
|
||||||
#
|
#
|
||||||
class jasmine.GWT.Scenario extends jasmine.GWT.Background
|
class jasmine.GWT.Scenario extends jasmine.GWT.Background
|
||||||
constructor: (scenarioName, code, @feature) ->
|
@runCode: (type, name, param, position, context, args = []) ->
|
||||||
super(code)
|
it "#{type} #{name}", ->
|
||||||
|
if position == 'first'
|
||||||
|
jasmine.GWT.runHook('World', context)
|
||||||
|
jasmine.GWT.runHook('Before', context)
|
||||||
|
|
||||||
|
this.spyOn = (args...) ->
|
||||||
|
this.spies_ = context.spies_
|
||||||
|
jasmine.Spec.prototype.spyOn.apply(this, args)
|
||||||
|
|
||||||
|
this.removeAllSpies = ->
|
||||||
|
if position == 'last'
|
||||||
|
jasmine.Spec.prototype.removeAllSpies.apply(context)
|
||||||
|
|
||||||
|
param.apply(context, args)
|
||||||
|
|
||||||
|
if position == 'last'
|
||||||
|
jasmine.GWT.runHook('After', context)
|
||||||
|
|
||||||
|
@runFailure: (type, name, args) ->
|
||||||
|
it "#{type} #{name}", ->
|
||||||
|
output = [ "", "No step defined for #{type} #{name}. Define one using the following:", '' ]
|
||||||
|
output = output.concat(jasmine.GWT.Scenario.generateStepDefinition(type, name, args))
|
||||||
|
output.push("")
|
||||||
|
|
||||||
|
this.addMatcherResult(
|
||||||
|
jasmine.GWT.Scenario.generateNotDefinedResult(type, name, output.join("\n"))
|
||||||
|
)
|
||||||
|
|
||||||
|
@generateStepDefinition: (type, name, args) ->
|
||||||
|
output = []
|
||||||
|
|
||||||
|
argCount = args.length
|
||||||
|
|
||||||
|
name = name.replace /\d+/g, (match) ->
|
||||||
|
argCount += 1
|
||||||
|
"(\\d+)"
|
||||||
|
|
||||||
|
name = name.replace /\"[^"]+\"/g, (match) ->
|
||||||
|
argCount += 1
|
||||||
|
'"([^"]+)"'
|
||||||
|
|
||||||
|
if argCount == 0
|
||||||
|
output.push("#{type} /^#{name}$/, ->")
|
||||||
|
else
|
||||||
|
args = ("arg#{i}" for i in [ 1..(argCount) ])
|
||||||
|
|
||||||
|
output.push("#{type} /^#{name}$/, (#{args.join(', ')}) ->")
|
||||||
|
|
||||||
|
output.push(" @not_defined()")
|
||||||
|
output
|
||||||
|
|
||||||
|
@generateNotDefinedResult: (type, name, message) ->
|
||||||
|
new jasmine.ExpectationResult(
|
||||||
|
matcherName: 'step',
|
||||||
|
passed: false,
|
||||||
|
expected: 'to be defined',
|
||||||
|
actual: "#{type} #{name}",
|
||||||
|
message: message
|
||||||
|
)
|
||||||
|
|
||||||
|
constructor: (@scenarioName, @code, @feature) ->
|
||||||
|
super(@code)
|
||||||
|
|
||||||
|
run: =>
|
||||||
|
super()
|
||||||
|
|
||||||
|
jasmine.GWT.currentScenario_ = this
|
||||||
|
|
||||||
_statements = this.allStatements()
|
_statements = this.allStatements()
|
||||||
_this = this
|
_this = this
|
||||||
|
|
||||||
describe @feature.name, ->
|
describe @feature.name, ->
|
||||||
describe scenarioName, ->
|
describe _this.scenarioName, ->
|
||||||
_this.spies_ = []
|
_this.spies_ = []
|
||||||
|
|
||||||
|
position = 'first'
|
||||||
|
|
||||||
for index in [ 0..._statements.length ]
|
for index in [ 0..._statements.length ]
|
||||||
[ type, name, param ] = _statements[index]
|
[ type, name, param ] = _statements[index]
|
||||||
|
[ _this._type, _this._name ] = [ type, name ]
|
||||||
_this._type = type
|
|
||||||
_this._name = name
|
|
||||||
|
|
||||||
runCode = (param, index, args = []) ->
|
|
||||||
isLast = (index + 1) == _statements.length
|
|
||||||
isFirst = (index == 0)
|
|
||||||
|
|
||||||
it "#{type} #{name}", ->
|
|
||||||
if isFirst
|
|
||||||
jasmine.GWT.runHook('World', _this)
|
|
||||||
jasmine.GWT.runHook('Before', _this)
|
|
||||||
|
|
||||||
this.spyOn = (args...) ->
|
|
||||||
this.spies_ = _this.spies_
|
|
||||||
jasmine.Spec.prototype.spyOn.apply(this, args)
|
|
||||||
|
|
||||||
this.removeAllSpies = ->
|
|
||||||
if isLast
|
|
||||||
jasmine.Spec.prototype.removeAllSpies.apply(_this)
|
|
||||||
|
|
||||||
param.apply(_this, args)
|
|
||||||
|
|
||||||
if isLast
|
|
||||||
jasmine.GWT.runHook('After', _this)
|
|
||||||
|
|
||||||
runFailure = (type, name, args) ->
|
|
||||||
it "#{type} #{name}", ->
|
|
||||||
output = [ "", "No step defined for #{type} #{name}. Define one using the following:", '' ]
|
|
||||||
|
|
||||||
argCount = args.length
|
|
||||||
|
|
||||||
name = name.replace /\d+/g, (match) ->
|
|
||||||
argCount += 1
|
|
||||||
"(\\d+)"
|
|
||||||
|
|
||||||
name = name.replace /\"[^"]+\"/g, (match) ->
|
|
||||||
argCount += 1
|
|
||||||
'"([^"]+)"'
|
|
||||||
|
|
||||||
if argCount == 0
|
|
||||||
output.push("#{type} /^#{name}$/, ->")
|
|
||||||
else
|
|
||||||
args = ("arg#{i}" for i in [ 1..(argCount) ])
|
|
||||||
|
|
||||||
output.push("#{type} /^#{name}$/, (#{args.join(', ')}) ->")
|
|
||||||
|
|
||||||
output.push(" @not_defined()")
|
|
||||||
output.push("")
|
|
||||||
|
|
||||||
this.addMatcherResult(
|
|
||||||
new jasmine.ExpectationResult(
|
|
||||||
matcherName: 'steps',
|
|
||||||
passed: false,
|
|
||||||
expected: 'to be defined',
|
|
||||||
actual: "#{type} #{name}",
|
|
||||||
message: output.join("\n")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
args = []
|
args = []
|
||||||
|
|
||||||
|
codeRunner = (thing, args = []) ->
|
||||||
|
jasmine.GWT.Scenario.runCode(type, name, thing, position, _this, args)
|
||||||
|
|
||||||
if param?
|
if param?
|
||||||
if typeof param == "function"
|
if typeof param == "function"
|
||||||
runCode(param, index)
|
codeRunner(param)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
args = [ param ]
|
args = [ param ]
|
||||||
|
|
||||||
found = false
|
found = false
|
||||||
|
|
||||||
if jasmine.GWT.Steps[type]
|
for [ match, code ] in (jasmine.GWT.Steps[type] || [])
|
||||||
for [ match, code ] in jasmine.GWT.Steps[type]
|
if result = name.match(match)
|
||||||
if match.constructor == RegExp
|
codeRunner(code, result[1..-1].concat(args))
|
||||||
if result = name.match(match)
|
found = true
|
||||||
result.shift()
|
|
||||||
runCode(code, index, result.concat(args))
|
|
||||||
found = true
|
|
||||||
|
|
||||||
break
|
break
|
||||||
else
|
|
||||||
if name == match
|
|
||||||
runCode(code, index)
|
|
||||||
found = true
|
|
||||||
|
|
||||||
break
|
jasmine.GWT.Scenario.runFailure(type, name, args) if !found
|
||||||
|
|
||||||
runFailure(type, name, args) if !found
|
position = (if (index + 2) == _statements.length then 'last' else 'middle')
|
||||||
|
|
||||||
|
jasmine.GWT.currentScenario_ = null
|
||||||
|
|
||||||
allStatements: =>
|
allStatements: =>
|
||||||
allStatements = []
|
allStatements = []
|
||||||
@ -111,12 +120,6 @@ class jasmine.GWT.Scenario extends jasmine.GWT.Background
|
|||||||
allStatements.concat(@statements)
|
allStatements.concat(@statements)
|
||||||
|
|
||||||
not_defined: =>
|
not_defined: =>
|
||||||
fakeResult = new jasmine.ExpectationResult(
|
fakeResult = jasmine.GWT.Scenario.generateNotDefinedResult(@_type, @_name, 'has no code defined.')
|
||||||
matcherName: 'step',
|
|
||||||
passed: false,
|
|
||||||
expected: 'to be defined',
|
|
||||||
actual: "#{@_type} #{@_name}",
|
|
||||||
message: "has no code defined."
|
|
||||||
)
|
|
||||||
|
|
||||||
jasmine.getEnv().currentSpec.addMatcherResult(fakeResult)
|
jasmine.getEnv().currentSpec.addMatcherResult(fakeResult)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
jasmine.GWT.globals =
|
jasmine.GWT.globals =
|
||||||
Feature: (args...) ->
|
Feature: (args...) ->
|
||||||
new jasmine.GWT.Feature(args...)
|
feature = new jasmine.GWT.Feature(args...)
|
||||||
|
feature.run()
|
||||||
|
|
||||||
Background: (args...) ->
|
Background: (args...) ->
|
||||||
jasmine.GWT.currentFeature_.Background(args...)
|
jasmine.GWT.currentFeature_.Background(args...)
|
||||||
|
45
spec/javascripts/cabiai_spec.js.coffee
Normal file
45
spec/javascripts/cabiai_spec.js.coffee
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#= require cabiai
|
||||||
|
#
|
||||||
|
describe 'Cabiai', ->
|
||||||
|
cabiai = null
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
Cabiai.viewSource = -> @view
|
||||||
|
|
||||||
|
cabiai = {}
|
||||||
|
|
||||||
|
cabiai[method] = code for method, code of Cabiai.Actions
|
||||||
|
|
||||||
|
describe 'Actions#clickOn', ->
|
||||||
|
context 'button', ->
|
||||||
|
text = "text"
|
||||||
|
isClicked = false
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
cabiai.view = $("<div><button>#{text}</button></div>")
|
||||||
|
$('button', cabiai.view).click -> isClicked = true
|
||||||
|
|
||||||
|
it 'should find a button by text', ->
|
||||||
|
cabiai.clickOn(text)
|
||||||
|
expect(isClicked).toEqual(true)
|
||||||
|
|
||||||
|
it 'should not find it' , ->
|
||||||
|
try
|
||||||
|
cabiai.clickOn('other')
|
||||||
|
expect("throw exception").toEqual(false)
|
||||||
|
catch e
|
||||||
|
expect(e.message).toMatch(/Button not found: other/)
|
||||||
|
|
||||||
|
describe 'Actions#within', ->
|
||||||
|
beforeEach ->
|
||||||
|
cabiai.view = $('<div><li>One</li><li>Two</li></div>')
|
||||||
|
|
||||||
|
it 'should focus an action within a selector', ->
|
||||||
|
currentView = null
|
||||||
|
|
||||||
|
cabiai.within 'li:eq(1)', ->
|
||||||
|
currentView = this._view()
|
||||||
|
|
||||||
|
expect(currentView).toEqual($('li:eq(1)', cabiai.view))
|
||||||
|
|
||||||
|
|
@ -61,3 +61,33 @@ describe 'jasmine.GWT', ->
|
|||||||
jasmine.GWT.World(func)
|
jasmine.GWT.World(func)
|
||||||
expect(jasmine.GWT.Hook).toHaveBeenCalledWith('World', func)
|
expect(jasmine.GWT.Hook).toHaveBeenCalledWith('World', func)
|
||||||
|
|
||||||
|
describe '.runHook', ->
|
||||||
|
object = null
|
||||||
|
value = 'value'
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
object = {}
|
||||||
|
jasmine.GWT.Hooks['Hooks'] = [
|
||||||
|
-> this.value = value
|
||||||
|
]
|
||||||
|
|
||||||
|
it 'should run all the code in the hooks', ->
|
||||||
|
jasmine.GWT.runHook('Hooks', object)
|
||||||
|
|
||||||
|
expect(object.value).toEqual(value)
|
||||||
|
|
||||||
|
describe '.generateWoldMethods', ->
|
||||||
|
object = null
|
||||||
|
method = ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
object =
|
||||||
|
method: method
|
||||||
|
|
||||||
|
it 'should add methods to the object', ->
|
||||||
|
newObject = {}
|
||||||
|
runner = jasmine.GWT.generateWorldMethods(object)
|
||||||
|
|
||||||
|
runner.apply(newObject)
|
||||||
|
expect(newObject.method).toEqual(method)
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
src_dir: lib/assets/javascripts
|
src_dir: lib/assets/javascripts
|
||||||
src_files: [ 'jasmine-gwt.js.coffee' ]
|
src_files: [ 'jasmine-gwt.js.coffee', 'cabiai.js.coffee' ]
|
||||||
|
|
||||||
spec_dir: spec/javascripts
|
spec_dir: spec/javascripts
|
||||||
spec_files: [ '**/*_spec.coffee' ]
|
spec_files: [ '**/*_spec.*', '*_spec.*' ]
|
||||||
|
|
||||||
helpers: [ 'spec_helper.coffee' ]
|
helpers: [ 'spec_helper.coffee' ]
|
||||||
|
Loading…
Reference in New Issue
Block a user