zucchini-ios 0.6.2 → 0.7.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/.travis.yml +11 -1
- data/CHANGELOG.md +6 -0
- data/lib/zucchini.rb +2 -0
- data/lib/zucchini/compiler.rb +59 -0
- data/lib/zucchini/config.rb +19 -15
- data/lib/zucchini/detector.rb +5 -19
- data/lib/zucchini/device.rb +32 -0
- data/lib/zucchini/feature.rb +7 -22
- data/lib/zucchini/runner.rb +1 -2
- data/lib/zucchini/uia/lib/compat.coffee +9 -0
- data/lib/zucchini/uia/lib/mechanic.js +556 -0
- data/lib/zucchini/uia/lib/uia.coffee +14 -0
- data/lib/zucchini/uia/lib/util.coffee +41 -0
- data/lib/zucchini/uia/screen.coffee +29 -31
- data/lib/zucchini/uia/zucchini.coffee +32 -0
- data/lib/zucchini/version.rb +1 -1
- data/spec/lib/zucchini/compiler_spec.rb +40 -0
- data/spec/lib/zucchini/config_spec.rb +6 -14
- data/spec/lib/zucchini/detector_spec.rb +1 -1
- data/spec/lib/zucchini/feature_spec.rb +1 -25
- data/spec/spec_helper.rb +3 -6
- metadata +12 -4
- data/lib/zucchini/uia/base.coffee +0 -89
@@ -0,0 +1,14 @@
|
|
1
|
+
# Expose global objects to the user
|
2
|
+
target = UIATarget.localTarget()
|
3
|
+
app = target.frontMostApp()
|
4
|
+
view = app.mainWindow()
|
5
|
+
|
6
|
+
# Prevent UIA from auto handling alerts
|
7
|
+
UIATarget.onAlert = (alert) -> return true
|
8
|
+
|
9
|
+
# Prepend screenshot names with numbers
|
10
|
+
screensCount = 0
|
11
|
+
target.captureScreenWithName_ = target.captureScreenWithName
|
12
|
+
target.captureScreenWithName = (name) ->
|
13
|
+
number = (if (++screensCount < 10) then "0#{screensCount}" else screensCount)
|
14
|
+
@captureScreenWithName_ "#{number}_#{name}"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
Function::bind = (context) ->
|
2
|
+
return this unless context
|
3
|
+
fun = this
|
4
|
+
-> fun.apply context, arguments
|
5
|
+
|
6
|
+
String::camelCase = ->
|
7
|
+
@replace /([\-\ ][A-Za-z])/g, ($1) ->
|
8
|
+
$1.toUpperCase().replace /[\-\ ]/g, ''
|
9
|
+
|
10
|
+
# Instruments >= 4.5 crash when a JS primitive is thrown
|
11
|
+
# http://apple.stackexchange.com/questions/69484/unknown-xcode-instruments-crash
|
12
|
+
raise = (message) -> throw new Error(message)
|
13
|
+
|
14
|
+
# A finder could return an UIAElement or an array from a mechanic.js selector
|
15
|
+
# Handle both cases
|
16
|
+
_elementFrom = (finder) ->
|
17
|
+
res = finder()
|
18
|
+
res = res[0] if (typeof res.length is 'number')
|
19
|
+
res
|
20
|
+
|
21
|
+
# Execute a finder function until the element appears
|
22
|
+
wait = (finder) ->
|
23
|
+
found = false
|
24
|
+
counter = 0
|
25
|
+
element = null
|
26
|
+
|
27
|
+
while not found and (counter < 10)
|
28
|
+
element = _elementFrom finder
|
29
|
+
|
30
|
+
if element? and element.isValid() and element.isVisible()
|
31
|
+
found = true
|
32
|
+
else
|
33
|
+
target.delay 0.5
|
34
|
+
counter++
|
35
|
+
if found then element else false
|
36
|
+
|
37
|
+
rotateTo = (orientation) ->
|
38
|
+
target.setDeviceOrientation(
|
39
|
+
if orientation is 'portrait' then UIA_DEVICE_ORIENTATION_PORTRAIT
|
40
|
+
else UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT
|
41
|
+
)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class Screen
|
2
|
-
takeScreenshot: (
|
2
|
+
takeScreenshot: (screenshotName) ->
|
3
|
+
$.delay 0.5
|
3
4
|
orientation = switch app.interfaceOrientation()
|
4
5
|
when 0 then 'Unknown'
|
5
6
|
when 1 then 'Portrait'
|
@@ -8,51 +9,53 @@ class Screen
|
|
8
9
|
when 4 then 'LandscapeRight'
|
9
10
|
when 5 then 'FaceUp'
|
10
11
|
when 6 then 'FaceDown'
|
11
|
-
|
12
|
-
target.captureScreenWithName("#{orientation}_#{@name}-screen_#{
|
12
|
+
$.log "Screenshot of screen '#{@name}' taken"
|
13
|
+
target.captureScreenWithName("#{orientation}_#{@name}-screen_#{screenshotName}")
|
14
|
+
|
15
|
+
element: (name) ->
|
16
|
+
finder = @elements[name] || -> $('#' + name)
|
17
|
+
|
18
|
+
unless el = wait finder
|
19
|
+
raise "Element '#{name}' was not found on '#{@name}'"
|
20
|
+
el
|
13
21
|
|
14
22
|
constructor: (@name) ->
|
15
23
|
|
16
24
|
elements: {}
|
17
|
-
actions
|
18
|
-
'Take a screenshot$'
|
19
|
-
|
25
|
+
actions:
|
26
|
+
'Take a screenshot$': -> @takeScreenshot(@name)
|
27
|
+
|
28
|
+
'Take a screenshot named "([^"]*)"$': (name) -> @takeScreenshot(name)
|
20
29
|
|
21
|
-
'
|
22
|
-
@takeScreenshot(screenshot_name)
|
30
|
+
'Show elements' : -> view.logElementTree()
|
23
31
|
|
24
|
-
'
|
25
|
-
raise "Element '#{element}' not defined for the screen '#{@name}'" unless @elements[element]
|
26
|
-
@elements[element]().tap()
|
32
|
+
'Show elements for "([^"]*)"$': (name) -> @element(name).logElementTree()
|
27
33
|
|
28
|
-
'
|
29
|
-
@actions['Tap "([^"]*)"$'].bind(this)(element)
|
34
|
+
'Tap "([^"]*)"$': (name) -> @element(name).tap()
|
30
35
|
|
31
|
-
'
|
32
|
-
target.delay(seconds)
|
36
|
+
'Confirm "([^"]*)"$': (element) -> @actions['Tap "([^"]*)"$'].bind(this)(element)
|
33
37
|
|
34
|
-
'
|
35
|
-
|
36
|
-
|
38
|
+
'Wait for "([^"]*)" second[s]*$': (seconds) -> target.delay(seconds)
|
39
|
+
|
40
|
+
'Type "([^"]*)" in the "([^"]*)" field$': (text, name) ->
|
41
|
+
@element(name).tap()
|
37
42
|
app.keyboard().typeString text
|
38
43
|
|
39
|
-
'Clear the "([^"]*)" field$': (element)
|
40
|
-
raise "Element '#{element}' not defined for the screen '#{@name}'" unless @elements[element]
|
41
|
-
@elements[element]().setValue ""
|
44
|
+
'Clear the "([^"]*)" field$': (name) -> @element(name).setValue ''
|
42
45
|
|
43
46
|
'Cancel the alert$' : ->
|
44
47
|
alert = app.alert()
|
45
|
-
raise "No alert found to dismiss on screen '#{@name}'"
|
48
|
+
raise "No alert found to dismiss on screen '#{@name}'" unless alert.isValid()
|
46
49
|
alert.cancelButton().tap()
|
47
50
|
|
48
51
|
'Confirm the alert$' : ->
|
49
52
|
alert = app.alert()
|
50
|
-
raise "No alert found to dismiss on screen '#{@name}'"
|
53
|
+
raise "No alert found to dismiss on screen '#{@name}'" unless alert.isValid()
|
51
54
|
alert.defaultButton().tap()
|
52
55
|
|
53
56
|
'Select the date "([^"]*)"$' : (dateString) ->
|
54
57
|
datePicker = view.pickers()[0]
|
55
|
-
raise "No date picker available to enter the date #{dateString}" unless (
|
58
|
+
raise "No date picker available to enter the date #{dateString}" unless datePicker.isValid() and datePicker.isVisible()
|
56
59
|
dateParts = dateString.match(/^(\d{2}) (\D*) (\d{4})$/)
|
57
60
|
raise "Date is in the wrong format. Need DD Month YYYY. Got #{dateString}" unless dateParts?
|
58
61
|
# Set Day
|
@@ -64,13 +67,8 @@ class Screen
|
|
64
67
|
counter++
|
65
68
|
monthWheel.tapWithOptions({tapOffset:{x:0.5, y:0.33}})
|
66
69
|
target.delay(0.4)
|
67
|
-
raise "
|
70
|
+
raise "Couldn't find the month #{dateParts[2]}" unless counter < 12
|
68
71
|
# Set Year
|
69
72
|
view.pickers()[0].wheels()[2].selectValue(dateParts[3])
|
70
73
|
|
71
|
-
'
|
72
|
-
view.logElementTree()
|
73
|
-
|
74
|
-
'Rotate device to "([^"]*)"$': (orientation) ->
|
75
|
-
orientation = if orientation == "landscape" then UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT else UIA_DEVICE_ORIENTATION_PORTRAIT
|
76
|
-
target.setDeviceOrientation(orientation)
|
74
|
+
'Rotate device to "([^"]*)"$': (orientation) -> rotateTo(orientation)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Run a Zucchini feature
|
2
|
+
Zucchini = (featureText, orientation) ->
|
3
|
+
rotateTo(orientation)
|
4
|
+
|
5
|
+
sections = featureText.trim().split(/\n\s*\n/)
|
6
|
+
|
7
|
+
for section in sections
|
8
|
+
lines = section.split(/\n/)
|
9
|
+
|
10
|
+
screenMatch = lines[0].match(/.+ on the "([^"]*)" screen:$/)
|
11
|
+
raise "Line '#{lines[0]}' doesn't define a screen context" unless screenMatch
|
12
|
+
|
13
|
+
screenName = screenMatch[1]
|
14
|
+
try
|
15
|
+
screen = eval("new #{screenName.camelCase()}Screen")
|
16
|
+
catch e
|
17
|
+
raise "Screen '#{screenName}' not defined"
|
18
|
+
|
19
|
+
if screen.anchor
|
20
|
+
if wait(screen.anchor)
|
21
|
+
$.log "Found anchor for screen '#{screenName}'"
|
22
|
+
else
|
23
|
+
raise "Could not find anchor for screen '#{screenName}'"
|
24
|
+
|
25
|
+
for line in lines.slice(1)
|
26
|
+
functionFound = false
|
27
|
+
for regExpText, func of screen.actions
|
28
|
+
match = line.trim().match(new RegExp(regExpText))
|
29
|
+
if match
|
30
|
+
functionFound = true
|
31
|
+
func.bind(screen)(match[1],match[2])
|
32
|
+
raise "Action for line '#{line}' not defined" unless functionFound
|
data/lib/zucchini/version.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zucchini::Compiler do
|
4
|
+
let(:path) { './spec/sample_setup/feature_one' }
|
5
|
+
let(:feature) { Zucchini::Feature.new(path) }
|
6
|
+
|
7
|
+
after(:all) { FileUtils.rm_rf Dir.glob("#{path}/run_data/feature.*") }
|
8
|
+
|
9
|
+
describe "#compile_js" do
|
10
|
+
before { feature.compile_js 'landscape' }
|
11
|
+
|
12
|
+
it "should strip comments from the feature file" do
|
13
|
+
File.read("#{feature.run_data_path}/feature.coffee").index('#').should be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "feature.js output" do
|
17
|
+
subject { File.read("#{feature.run_data_path}/feature.js") }
|
18
|
+
|
19
|
+
it "should include mechanic.js" do
|
20
|
+
should match /mechanic\.js UIAutomation Library/
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should include screen definitions" do
|
24
|
+
should match /SplashScreen = \(function/
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should include Zucchini runtime" do
|
28
|
+
should match /Zucchini = function/
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should include custom libraries from support/lib" do
|
32
|
+
should match /Helpers.example = /
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should include screen orientation" do
|
36
|
+
should match /Zucchini\(.+\'landscape\'\)/
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -16,25 +16,25 @@ describe Zucchini::Config do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
describe "device" do
|
21
21
|
before(:all) { Zucchini::Config.base_path = "spec/sample_setup" }
|
22
22
|
|
23
23
|
context "device present in config.yml" do
|
24
24
|
it "should return the device hash" do
|
25
|
-
Zucchini::Config.device("My iDevice").should eq({:name =>"My iDevice", :udid =>"lolffb28d74a6fraj2156090784avasc50725dd0", :screen =>"ipad_ios5"})
|
25
|
+
Zucchini::Config.device("My iDevice").should eq({:name =>"My iDevice", :udid =>"lolffb28d74a6fraj2156090784avasc50725dd0", :screen =>"ipad_ios5", :simulator=>nil, :orientation=> 'portrait'})
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
context "device not present in config.yml" do
|
30
30
|
it "should raise an error" do
|
31
|
-
expect { Zucchini::Config.device("My Android Phone")}.to raise_error "Device not listed in config.yml"
|
31
|
+
expect { Zucchini::Config.device("My Android Phone")}.to raise_error "Device 'My Android Phone' not listed in config.yml"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
context "default device" do
|
36
36
|
it "should use default device if device name argument is nil" do
|
37
|
-
Zucchini::Config.device(nil).should eq({:name =>"Default Device", :screen =>"low_ios5", :udid => nil})
|
37
|
+
Zucchini::Config.device(nil).should eq({:name =>"Default Device", :screen =>"low_ios5", :udid => nil, :simulator=>nil, :orientation=> 'portrait'})
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should raise error if no default device provided" do
|
@@ -43,12 +43,4 @@ describe Zucchini::Config do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
|
-
describe "url" do
|
48
|
-
before(:all) { Zucchini::Config.base_path = "spec/sample_setup" }
|
49
|
-
|
50
|
-
it "should return a full URL string for a given server name" do
|
51
|
-
Zucchini::Config.url('backend', '/api').should eq "http://192.168.1.2:8080/api"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
46
|
+
end
|
@@ -18,7 +18,7 @@ describe Zucchini::Detector do
|
|
18
18
|
|
19
19
|
context "device hasn't been found" do
|
20
20
|
before { ENV['ZUCCHINI_DEVICE'] = 'My Android Phone' }
|
21
|
-
it { should raise_error "Device not listed in config.yml" }
|
21
|
+
it { should raise_error "Device 'My Android Phone' not listed in config.yml" }
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -3,32 +3,8 @@ require 'spec_helper'
|
|
3
3
|
describe Zucchini::Feature do
|
4
4
|
let(:path) { './spec/sample_setup/feature_one' }
|
5
5
|
let(:feature) { Zucchini::Feature.new(path) }
|
6
|
-
|
6
|
+
|
7
7
|
after(:all) { FileUtils.rm_rf Dir.glob("#{path}/run_data/feature.*") }
|
8
|
-
|
9
|
-
describe "#compile_js" do
|
10
|
-
before { feature.compile_js }
|
11
|
-
|
12
|
-
it "should strip comments from the feature file" do
|
13
|
-
File.read("#{feature.run_data_path}/feature.coffee").index('#').should be_nil
|
14
|
-
end
|
15
|
-
|
16
|
-
describe "feature.js output" do
|
17
|
-
subject { File.read("#{feature.run_data_path}/feature.js") }
|
18
|
-
|
19
|
-
it "should include screen definitions" do
|
20
|
-
should match /SplashScreen = \(function/
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should include Zucchini runtime" do
|
24
|
-
should match /Zucchini.run = /
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should include custom libraries from support/lib" do
|
28
|
-
should match /Helpers.example = /
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
8
|
|
33
9
|
describe "approve" do
|
34
10
|
subject { lambda { feature.approve "reference" } }
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,10 @@
|
|
1
1
|
require 'coveralls'
|
2
2
|
require 'simplecov'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
else
|
7
|
-
SimpleCov.start do
|
8
|
-
add_filter "/spec/"
|
9
|
-
end
|
4
|
+
SimpleCov.start do
|
5
|
+
add_filter "/spec/"
|
10
6
|
end
|
7
|
+
Coveralls.wear! if ENV['COVERAGE'] == 'coveralls'
|
11
8
|
|
12
9
|
require 'clamp'
|
13
10
|
require 'fileutils'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zucchini-ios
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-08-
|
14
|
+
date: 2013-08-11 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: clamp
|
@@ -96,8 +96,10 @@ files:
|
|
96
96
|
- bin/zucchini
|
97
97
|
- lib/zucchini.rb
|
98
98
|
- lib/zucchini/approver.rb
|
99
|
+
- lib/zucchini/compiler.rb
|
99
100
|
- lib/zucchini/config.rb
|
100
101
|
- lib/zucchini/detector.rb
|
102
|
+
- lib/zucchini/device.rb
|
101
103
|
- lib/zucchini/feature.rb
|
102
104
|
- lib/zucchini/generator.rb
|
103
105
|
- lib/zucchini/report.rb
|
@@ -110,9 +112,14 @@ files:
|
|
110
112
|
- lib/zucchini/report/view.rb
|
111
113
|
- lib/zucchini/runner.rb
|
112
114
|
- lib/zucchini/screenshot.rb
|
113
|
-
- lib/zucchini/uia/
|
115
|
+
- lib/zucchini/uia/lib/compat.coffee
|
116
|
+
- lib/zucchini/uia/lib/mechanic.js
|
117
|
+
- lib/zucchini/uia/lib/uia.coffee
|
118
|
+
- lib/zucchini/uia/lib/util.coffee
|
114
119
|
- lib/zucchini/uia/screen.coffee
|
120
|
+
- lib/zucchini/uia/zucchini.coffee
|
115
121
|
- lib/zucchini/version.rb
|
122
|
+
- spec/lib/zucchini/compiler_spec.rb
|
116
123
|
- spec/lib/zucchini/config_spec.rb
|
117
124
|
- spec/lib/zucchini/detector_spec.rb
|
118
125
|
- spec/lib/zucchini/feature_spec.rb
|
@@ -176,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
183
|
version: '0'
|
177
184
|
segments:
|
178
185
|
- 0
|
179
|
-
hash: -
|
186
|
+
hash: -3527198499352191037
|
180
187
|
requirements: []
|
181
188
|
rubyforge_project:
|
182
189
|
rubygems_version: 1.8.23
|
@@ -184,6 +191,7 @@ signing_key:
|
|
184
191
|
specification_version: 3
|
185
192
|
summary: Functional testing framework for iOS-powered devices
|
186
193
|
test_files:
|
194
|
+
- spec/lib/zucchini/compiler_spec.rb
|
187
195
|
- spec/lib/zucchini/config_spec.rb
|
188
196
|
- spec/lib/zucchini/detector_spec.rb
|
189
197
|
- spec/lib/zucchini/feature_spec.rb
|
@@ -1,89 +0,0 @@
|
|
1
|
-
Function::bind = (context) ->
|
2
|
-
return this unless context
|
3
|
-
fun = this
|
4
|
-
->
|
5
|
-
fun.apply context, arguments
|
6
|
-
|
7
|
-
String::camelCase = ->
|
8
|
-
@replace /([\-\ ][A-Za-z])/g, ($1) ->
|
9
|
-
$1.toUpperCase().replace /[\-\ ]/g, ""
|
10
|
-
|
11
|
-
extend = (obj, mixin) ->
|
12
|
-
obj[name] = method for name, method of mixin
|
13
|
-
obj
|
14
|
-
|
15
|
-
puts = (text) -> UIALogger.logMessage text
|
16
|
-
|
17
|
-
# Instruments 4.5 crash when a JS primitive is thrown
|
18
|
-
# http://apple.stackexchange.com/questions/69484/unknown-xcode-instruments-crash
|
19
|
-
raise = (message) -> throw new Error(message)
|
20
|
-
|
21
|
-
# Prevent UIA from auto handling alerts
|
22
|
-
UIATarget.onAlert = (alert) -> return true
|
23
|
-
|
24
|
-
target = UIATarget.localTarget()
|
25
|
-
app = target.frontMostApp()
|
26
|
-
view = app.mainWindow()
|
27
|
-
|
28
|
-
UIAElement.prototype.$ = (name) ->
|
29
|
-
target.pushTimeout(0)
|
30
|
-
elem = null
|
31
|
-
for el in this.elements()
|
32
|
-
elem = if el.name() == name then el else el.$(name)
|
33
|
-
break if elem
|
34
|
-
target.popTimeout()
|
35
|
-
elem
|
36
|
-
|
37
|
-
target.waitForElement = (element) ->
|
38
|
-
return false unless element
|
39
|
-
found = false
|
40
|
-
counter = 0
|
41
|
-
while not found and (counter < 10)
|
42
|
-
if element.isValid() and element.isVisible()
|
43
|
-
found = true
|
44
|
-
else
|
45
|
-
@delay 0.5
|
46
|
-
counter++
|
47
|
-
return found
|
48
|
-
|
49
|
-
isNullElement = (elem) -> elem.toString() == "[object UIAElementNil]"
|
50
|
-
|
51
|
-
screensCount = 0
|
52
|
-
target.captureScreenWithName_ = target.captureScreenWithName
|
53
|
-
target.captureScreenWithName = (screenName) ->
|
54
|
-
screensCountText = (if (++screensCount < 10) then "0" + screensCount else screensCount)
|
55
|
-
@captureScreenWithName_ screensCountText + "_" + screenName
|
56
|
-
|
57
|
-
class Zucchini
|
58
|
-
@run: (featureText) ->
|
59
|
-
sections = featureText.trim().split(/\n\s*\n/)
|
60
|
-
|
61
|
-
for section in sections
|
62
|
-
lines = section.split(/\n/)
|
63
|
-
|
64
|
-
screenMatch = lines[0].match(/.+ on the "([^"]*)" screen:$/)
|
65
|
-
raise "Line '#{lines[0]}' doesn't define a screen context" unless screenMatch
|
66
|
-
|
67
|
-
screenName = screenMatch[1]
|
68
|
-
try
|
69
|
-
screen = eval("new #{screenName.camelCase()}Screen")
|
70
|
-
catch e
|
71
|
-
raise "Screen '#{screenName}' not defined"
|
72
|
-
|
73
|
-
if screen.anchor
|
74
|
-
element = screen.anchor()
|
75
|
-
found = target.waitForElement(element)
|
76
|
-
|
77
|
-
if found
|
78
|
-
puts "Found anchor for screen '#{screenName}'"
|
79
|
-
else
|
80
|
-
raise "Could not find anchor for screen '#{screenName}'"
|
81
|
-
|
82
|
-
for line in lines.slice(1)
|
83
|
-
functionFound = false
|
84
|
-
for regExpText, func of screen.actions
|
85
|
-
match = line.trim().match(new RegExp(regExpText))
|
86
|
-
if match
|
87
|
-
functionFound = true
|
88
|
-
func.bind(screen)(match[1],match[2])
|
89
|
-
raise "Action for line '#{line}' not defined" unless functionFound
|