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 'guard-jasmine-headless-webkit', :path => '../guard-jasmine-headless-webkit'
|
||||
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
|
||||
constructor: (code) ->
|
||||
constructor: (@code) ->
|
||||
@statements = []
|
||||
|
||||
run: =>
|
||||
jasmine.GWT.currentScenario_ = this
|
||||
|
||||
code.apply(this)
|
||||
@code.apply(this)
|
||||
|
||||
jasmine.GWT.currentScenario_ = null
|
||||
|
||||
Given: (name, code) ->
|
||||
@statements.push([ 'Given', name, code ])
|
||||
When: (name, code) ->
|
||||
@statements.push([ 'When', name, code ])
|
||||
Then: (name, code) ->
|
||||
@statements.push([ 'Then', name, code ])
|
||||
Given: (name, code) => this.Step('Given', name, code)
|
||||
When: (name, code) => this.Step('When', name, code)
|
||||
Then: (name, code) => this.Step('Then', name, code)
|
||||
|
||||
Step: (type, name, code) =>
|
||||
@statements.push([ type, name, code ])
|
||||
|
||||
|
@ -1,15 +1,19 @@
|
||||
class jasmine.GWT.Feature
|
||||
constructor: (@name, code) ->
|
||||
constructor: (@name, @code) ->
|
||||
|
||||
run: =>
|
||||
jasmine.GWT.currentFeature_ = this
|
||||
|
||||
@background = null
|
||||
code.apply(this)
|
||||
@code.apply(this)
|
||||
|
||||
jasmine.GWT.currentFeature_ = null
|
||||
|
||||
Scenario: (name, code) ->
|
||||
new jasmine.GWT.Scenario(name, code, this)
|
||||
scenario = new jasmine.GWT.Scenario(name, code, this)
|
||||
scenario.run()
|
||||
|
||||
Background: (code) ->
|
||||
@background = new jasmine.GWT.Background(code)
|
||||
@background.run()
|
||||
|
||||
|
@ -1,106 +1,115 @@
|
||||
#= require jasmine/GWT/Background
|
||||
#
|
||||
class jasmine.GWT.Scenario extends jasmine.GWT.Background
|
||||
constructor: (scenarioName, code, @feature) ->
|
||||
super(code)
|
||||
@runCode: (type, name, param, position, context, args = []) ->
|
||||
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()
|
||||
_this = this
|
||||
|
||||
describe @feature.name, ->
|
||||
describe scenarioName, ->
|
||||
describe _this.scenarioName, ->
|
||||
_this.spies_ = []
|
||||
|
||||
position = 'first'
|
||||
|
||||
for index in [ 0..._statements.length ]
|
||||
[ type, name, param ] = _statements[index]
|
||||
|
||||
_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")
|
||||
)
|
||||
)
|
||||
[ _this._type, _this._name ] = [ type, name ]
|
||||
|
||||
args = []
|
||||
|
||||
codeRunner = (thing, args = []) ->
|
||||
jasmine.GWT.Scenario.runCode(type, name, thing, position, _this, args)
|
||||
|
||||
if param?
|
||||
if typeof param == "function"
|
||||
runCode(param, index)
|
||||
codeRunner(param)
|
||||
|
||||
continue
|
||||
else
|
||||
args = [ param ]
|
||||
|
||||
found = false
|
||||
|
||||
if jasmine.GWT.Steps[type]
|
||||
for [ match, code ] in jasmine.GWT.Steps[type]
|
||||
if match.constructor == RegExp
|
||||
if result = name.match(match)
|
||||
result.shift()
|
||||
runCode(code, index, result.concat(args))
|
||||
found = true
|
||||
for [ match, code ] in (jasmine.GWT.Steps[type] || [])
|
||||
if result = name.match(match)
|
||||
codeRunner(code, result[1..-1].concat(args))
|
||||
found = true
|
||||
|
||||
break
|
||||
else
|
||||
if name == match
|
||||
runCode(code, index)
|
||||
found = true
|
||||
break
|
||||
|
||||
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 = []
|
||||
@ -111,12 +120,6 @@ class jasmine.GWT.Scenario extends jasmine.GWT.Background
|
||||
allStatements.concat(@statements)
|
||||
|
||||
not_defined: =>
|
||||
fakeResult = new jasmine.ExpectationResult(
|
||||
matcherName: 'step',
|
||||
passed: false,
|
||||
expected: 'to be defined',
|
||||
actual: "#{@_type} #{@_name}",
|
||||
message: "has no code defined."
|
||||
)
|
||||
fakeResult = jasmine.GWT.Scenario.generateNotDefinedResult(@_type, @_name, 'has no code defined.')
|
||||
|
||||
jasmine.getEnv().currentSpec.addMatcherResult(fakeResult)
|
||||
|
@ -1,6 +1,7 @@
|
||||
jasmine.GWT.globals =
|
||||
Feature: (args...) ->
|
||||
new jasmine.GWT.Feature(args...)
|
||||
feature = new jasmine.GWT.Feature(args...)
|
||||
feature.run()
|
||||
|
||||
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)
|
||||
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_files: [ 'jasmine-gwt.js.coffee' ]
|
||||
src_files: [ 'jasmine-gwt.js.coffee', 'cabiai.js.coffee' ]
|
||||
|
||||
spec_dir: spec/javascripts
|
||||
spec_files: [ '**/*_spec.coffee' ]
|
||||
spec_files: [ '**/*_spec.*', '*_spec.*' ]
|
||||
|
||||
helpers: [ 'spec_helper.coffee' ]
|
||||
|
Loading…
Reference in New Issue
Block a user