lapis_lazuli 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/lapis_lazuli/browser/find.rb +18 -9
- data/lib/lapis_lazuli/browser/screenshots.rb +73 -53
- data/lib/lapis_lazuli/generators/cucumber/template/config/config.yml +3 -2
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/validation_steps.rb +1 -1
- data/lib/lapis_lazuli/version.rb +1 -1
- data/lib/lapis_lazuli/world/error.rb +1 -1
- data/test/config/config.yml +2 -1
- data/test/features/bindings.feature +6 -6
- data/test/features/multifind.feature +52 -0
- data/test/features/screenshot.feature +35 -0
- data/test/features/step_definitions/interaction_steps.rb +8 -0
- data/test/features/step_definitions/multifind_steps.rb +136 -0
- data/test/features/step_definitions/validation_steps.rb +8 -9
- data/test/server/www/screenshot.html +147 -0
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05f31ca8e6b595e90bfdf4dd47a474e72a4cd1d3
|
4
|
+
data.tar.gz: 6e26fbb44ea553ea4e457f9f799c77da3a74ba20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4ecd69d51356464a628bb503d15135433960f56dcfcb2d1e5eb3875c16eb1241a72fd0bf9d1d77488461a99f5e6ef810ec41c33994b578b604273001d5e0ee5
|
7
|
+
data.tar.gz: 10b5b4124a3722b5b10222b4c8b3f7c9ff59454e04d15b97a35a124f84d478b0396bf86f7fe6737ef245474aa38fc999c5270ff289d4f105e28d0893a947d63b
|
@@ -109,7 +109,7 @@ module BrowserModule
|
|
109
109
|
def multi_find_all(*args)
|
110
110
|
# Parse args into options
|
111
111
|
options = {
|
112
|
-
:mode => :
|
112
|
+
:mode => :match_any,
|
113
113
|
}
|
114
114
|
options = parse_find_options(options, *args)
|
115
115
|
throw_opt, options = do_throw?(options)
|
@@ -170,7 +170,7 @@ module BrowserModule
|
|
170
170
|
:pick => :first,
|
171
171
|
:throw => true,
|
172
172
|
:mode => :match_one,
|
173
|
-
:error => nil
|
173
|
+
:error => nil
|
174
174
|
}
|
175
175
|
|
176
176
|
##
|
@@ -185,7 +185,7 @@ module BrowserModule
|
|
185
185
|
# Verify/sanitize common options
|
186
186
|
if options.has_key? :mode
|
187
187
|
options[:mode] = options[:mode].to_sym
|
188
|
-
assert [:match_all, :match_one].include?(options[:mode]), ":mode needs to be one of :match_one or :
|
188
|
+
assert [:match_all, :match_one, :match_any].include?(options[:mode]), ":mode needs to be one of :match_one, :match_all or :match_any"
|
189
189
|
end
|
190
190
|
|
191
191
|
if options.has_key? :pick
|
@@ -349,9 +349,8 @@ module BrowserModule
|
|
349
349
|
def find_lambda_filtered(options)
|
350
350
|
options = options.dup
|
351
351
|
|
352
|
-
filter_by = options.fetch(:filter_by,
|
352
|
+
filter_by = options.fetch(:filter_by, :present?)
|
353
353
|
options.delete(:filter_by)
|
354
|
-
|
355
354
|
options, inner = find_lambda(options)
|
356
355
|
|
357
356
|
# Wrap into filter function
|
@@ -420,15 +419,14 @@ module BrowserModule
|
|
420
419
|
s, func = find_lambda_filtered(selector)
|
421
420
|
lambdas << func
|
422
421
|
end
|
423
|
-
|
424
422
|
# Depending on mode, we need to execute something slightly different
|
425
423
|
case options[:mode]
|
426
|
-
when :match_all
|
424
|
+
when :match_all, :match_any
|
427
425
|
return options, lambda {
|
428
426
|
all = []
|
429
427
|
lambdas.each do |func|
|
430
428
|
res = func.call
|
431
|
-
if 0 == res.length
|
429
|
+
if 0 == res.length and options[:mode] == :match_all
|
432
430
|
all = []
|
433
431
|
break
|
434
432
|
end
|
@@ -485,7 +483,18 @@ module BrowserModule
|
|
485
483
|
ret = func.call
|
486
484
|
|
487
485
|
if throw_opt and (ret.nil? or ret.length <= 0)
|
488
|
-
|
486
|
+
msg = "Cannot find elements with selectors: "
|
487
|
+
if selectors[:selectors].length < 2
|
488
|
+
msg += "#{selectors[:selectors]}\n"
|
489
|
+
else
|
490
|
+
msg += "\n"
|
491
|
+
selectors[:selectors].each do |s|
|
492
|
+
msg += "- #{s} \n"
|
493
|
+
end
|
494
|
+
end
|
495
|
+
selectors.delete(:selectors)
|
496
|
+
msg += "With the options: #{selectors}"
|
497
|
+
raise msg
|
489
498
|
end
|
490
499
|
|
491
500
|
return ret
|
@@ -7,70 +7,90 @@
|
|
7
7
|
#
|
8
8
|
|
9
9
|
module LapisLazuli
|
10
|
-
module BrowserModule
|
10
|
+
module BrowserModule
|
11
11
|
|
12
|
-
##
|
13
|
-
# Screenshot functionality for browser
|
14
|
-
module Screenshots
|
15
12
|
##
|
16
|
-
#
|
17
|
-
|
18
|
-
|
13
|
+
# Screenshot functionality for browser
|
14
|
+
module Screenshots
|
15
|
+
##
|
16
|
+
# Returns the name of the screenshot, if take_screenshot is called now.
|
17
|
+
def screenshot_name(suffix="")
|
18
|
+
dir = world.env_or_config("screenshot_dir")
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
# Generate the file name according to the new or old scheme.
|
21
|
+
case world.env_or_config("screenshot_scheme")
|
22
|
+
when "new"
|
23
|
+
# For non-cucumber cases: we don't have world.scenario.data
|
24
|
+
if not world.scenario.data.nil?
|
25
|
+
name = world.scenario.id
|
26
|
+
end
|
27
|
+
# FIXME random makes this non-repeatable, sadly
|
28
|
+
name = "#{world.scenario.time[:iso_short]}-#{@browser.object_id}-#{name}-#{Random.rand(10000).to_s}.png"
|
29
|
+
else # 'old' and default
|
30
|
+
# For non-cucumber cases: we don't have world.scenario.data
|
31
|
+
if not world.scenario.data.nil?
|
32
|
+
name = world.scenario.data.name.gsub(/^.*(\\|\/)/, '').gsub(/[^\w\.\-]/, '_').squeeze('_')
|
33
|
+
end
|
34
|
+
name = world.time[:timestamp] + "_" + name + '.png'
|
26
35
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
name = world.scenario.data.name.gsub(/^.*(\\|\/)/, '').gsub(/[^\w\.\-]/, '_').squeeze('_')
|
33
|
-
end
|
34
|
-
name = world.time[:timestamp] + "_" + name + '.png'
|
36
|
+
|
37
|
+
# Full file location
|
38
|
+
fileloc = "#{dir}#{File::SEPARATOR}#{name}"
|
39
|
+
|
40
|
+
return fileloc
|
35
41
|
end
|
36
42
|
|
37
|
-
|
38
|
-
|
43
|
+
##
|
44
|
+
# Taking a screenshot of the current page.
|
45
|
+
# Using the name as defined at the start of every scenario
|
46
|
+
def take_screenshot(suffix="")
|
47
|
+
# If the target directory does not exist, create it.
|
48
|
+
dir = world.env_or_config("screenshot_dir")
|
49
|
+
begin
|
50
|
+
Dir.mkdir dir
|
51
|
+
rescue SystemCallError => ex
|
52
|
+
# Swallow this error; it occurs (amongst other situations) when the
|
53
|
+
# directory exists. Checking for an existing directory beforehand is
|
54
|
+
# not concurrency safe.
|
55
|
+
end
|
39
56
|
|
40
|
-
|
41
|
-
end
|
57
|
+
fileloc = self.screenshot_name(suffix)
|
42
58
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
59
|
+
# Write screenshot
|
60
|
+
begin
|
61
|
+
# First make sure the window size is the full page size
|
62
|
+
if world.env_or_config("screenshots_height") == 'full'
|
63
|
+
original_height = @browser.window.size.height
|
64
|
+
width = @browser.window.size.width
|
65
|
+
target_height = @browser.execute_script('
|
66
|
+
var body = document.body,
|
67
|
+
html = document.documentElement;
|
68
|
+
return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight );
|
69
|
+
')
|
70
|
+
if target_height > original_height
|
71
|
+
@browser.window.resize_to(width, target_height)
|
72
|
+
end
|
73
|
+
end
|
56
74
|
|
57
|
-
|
75
|
+
# Save the screenshot
|
76
|
+
@browser.screenshot.save fileloc
|
58
77
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
78
|
+
if world.env_or_config("screenshots_height") == 'full'
|
79
|
+
if target_height > original_height
|
80
|
+
@browser.window.resize_to(width, original_height)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
world.log.debug "Screenshot saved: #{fileloc}"
|
64
84
|
|
65
|
-
|
66
|
-
|
67
|
-
|
85
|
+
# Try to store the screenshot name
|
86
|
+
if world.respond_to? :annotate
|
87
|
+
world.annotate :screenshot => fileloc
|
88
|
+
end
|
89
|
+
rescue RuntimeError => e
|
90
|
+
world.log.debug "Failed to save screenshot to '#{fileloc}'. Error message #{e.message}"
|
68
91
|
end
|
69
|
-
|
70
|
-
world.log.debug "Failed to save screenshot to '#{fileloc}'. Error message #{e.message}"
|
92
|
+
return fileloc
|
71
93
|
end
|
72
|
-
|
73
|
-
|
74
|
-
end # module Screenshots
|
75
|
-
end # module BrowserModule
|
94
|
+
end # module Screenshots
|
95
|
+
end # module BrowserModule
|
76
96
|
end # module LapisLazuli
|
@@ -11,6 +11,7 @@
|
|
11
11
|
default_env: production # defines the environment
|
12
12
|
default_device: desktop720 # See devices.yml for your options
|
13
13
|
close_browser_after: end # Can be `scenario`, `feature` or `end`
|
14
|
+
screenshots_height: full # When 'full' the window will be resized to max height before taking a screenshot
|
14
15
|
|
15
16
|
################################################################################
|
16
17
|
# List of error strings. `browser.html_error` will return an array of detected strings.
|
@@ -36,7 +37,7 @@ uat:
|
|
36
37
|
|
37
38
|
production:
|
38
39
|
pages:
|
39
|
-
root: https://spritecloud.com
|
40
|
+
root: https://www.spritecloud.com
|
40
41
|
home: /
|
41
42
|
about-us: /about-us/
|
42
43
|
testing: /testing/
|
@@ -58,4 +59,4 @@ users:
|
|
58
59
|
password: test_RAND_
|
59
60
|
gender: 'Female'
|
60
61
|
experience: 'Ruby,Gherkin'
|
61
|
-
biography: 'Hello, I am a randomized user, today is _TIMESTAMP_ seconds after the existance of computers'
|
62
|
+
biography: 'Hello, I am a randomized user, today is _TIMESTAMP_ seconds after the existance of computers'
|
data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/validation_steps.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
# validation_steps.rb is used to confirm that certain elements are displayed on the page.
|
7
7
|
|
8
|
-
Then(
|
8
|
+
Then(/^text "([^"]*)" should display$/) do |string|
|
9
9
|
# Note: The following is *really* slow, as it'll apply the regex to all
|
10
10
|
# elements in the page, one after the other. Of course, if any element
|
11
11
|
# includes the regex, all its parent elements also will, so you have
|
data/lib/lapis_lazuli/version.rb
CHANGED
data/test/config/config.yml
CHANGED
@@ -9,8 +9,9 @@
|
|
9
9
|
################################################################################
|
10
10
|
# Set the global variables
|
11
11
|
default_env: production # defines the environment
|
12
|
-
default_device: desktop720
|
12
|
+
default_device: desktop720 # set the default browser dimensions and/or user agent (See devices.yml)
|
13
13
|
screenshots_dir: screenshots # where to save the screenshots
|
14
|
+
screenshots_height: full # When 'full' the window will be resized to max height before taking a screenshot
|
14
15
|
step_pause_time: 1 # Waiting time in seconds defined after a step completes
|
15
16
|
make_screenshot_on_failed_scenario: true # make a screenshot after a scenario fails
|
16
17
|
old_portal: true
|
@@ -5,14 +5,14 @@ I want to run a webserver with some test files
|
|
5
5
|
And test if I can parse bindings when starting the browsers
|
6
6
|
|
7
7
|
@bindings_01
|
8
|
-
Scenario: Custom user-agent firefox
|
8
|
+
Scenario: bindings_01 - Custom user-agent firefox
|
9
9
|
Given I use browser bindings "1"
|
10
10
|
And I navigate to URL "http://whatsmyua.com/"
|
11
11
|
Then within 2 seconds I should see "CUSTOM-USER-AGENT"
|
12
12
|
And I close the browser
|
13
13
|
|
14
14
|
@bindings_02
|
15
|
-
Scenario: Custom user-agent chrome
|
15
|
+
Scenario: bindings_02 - Custom user-agent chrome
|
16
16
|
Given I use browser bindings "2"
|
17
17
|
And I navigate to URL "http://whatsmyua.com/"
|
18
18
|
Then within 2 seconds I should see "CUSTOM-CHROME-USER-AGENT"
|
@@ -20,22 +20,22 @@ And test if I can parse bindings when starting the browsers
|
|
20
20
|
|
21
21
|
# Known issue with maximizing the window using the chrome option --start-maximized
|
22
22
|
@bindings_03 @maximize_issue
|
23
|
-
Scenario: Custom user-agent chrome
|
23
|
+
Scenario: bindings_03 - Custom user-agent chrome
|
24
24
|
Given I use browser bindings "3"
|
25
25
|
And I navigate to URL "http://whatsmyua.com/"
|
26
26
|
Then the browser window size should be "full screen"
|
27
27
|
And I close the browser
|
28
28
|
|
29
29
|
@bindings_04
|
30
|
-
Scenario: Using a pre-defined device (iphone5)
|
30
|
+
Scenario: bindings_04 - Using a pre-defined device (iphone5)
|
31
31
|
Given I restart the browser to device setting "iphone5"
|
32
32
|
When I navigate to URL "http://whatsmyua.com"
|
33
|
-
Then within 2 seconds I should see "
|
33
|
+
Then within 2 seconds I should see "CPU iPhone OS 5_0 like Mac OS X"
|
34
34
|
And the browser window size should be "640x1136"
|
35
35
|
And I close the browser
|
36
36
|
|
37
37
|
@bindings_05
|
38
|
-
Scenario: Using a pre-defined device (desktop1080)
|
38
|
+
Scenario: bindings_05 - Using a pre-defined device (desktop1080)
|
39
39
|
Given I restart the browser to device setting "desktop1080"
|
40
40
|
When I navigate to URL "http://whatsmyua.com"
|
41
41
|
Then within 2 seconds I should see "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3" disappear
|
@@ -0,0 +1,52 @@
|
|
1
|
+
@multifind @p
|
2
|
+
Feature: testing multifind
|
3
|
+
|
4
|
+
@multifind01
|
5
|
+
Scenario: multifind01 - multifind with 1 results
|
6
|
+
Given I navigate to the find test page
|
7
|
+
Then the user expects a result in a multi_find lookup
|
8
|
+
|
9
|
+
@multifind02
|
10
|
+
Scenario: multifind02 - multifind no results
|
11
|
+
Given I navigate to the find test page
|
12
|
+
Then the user expects an error in a multi_find lookup
|
13
|
+
|
14
|
+
@multifind03
|
15
|
+
Scenario: multifind03 - multifind with no results and no error
|
16
|
+
Given I navigate to the find test page
|
17
|
+
Then the user expects no error in a multi_find lookup
|
18
|
+
|
19
|
+
@multifind04
|
20
|
+
Scenario: multifind04 - multifind all with 8 results
|
21
|
+
Given I navigate to the find test page
|
22
|
+
Then the user expects 8 results in a multi_find_all lookup
|
23
|
+
|
24
|
+
@multifind05
|
25
|
+
Scenario: multifind05 - multifind all with 1 results
|
26
|
+
Given I navigate to the find test page
|
27
|
+
Then the user expects 1 results in a multi_find_all lookup
|
28
|
+
|
29
|
+
@multifind06
|
30
|
+
Scenario: multifind06 - multifind all with 5 results
|
31
|
+
Given I navigate to the find test page
|
32
|
+
Then the user expects 5 existing results in a multi_find_all lookup
|
33
|
+
|
34
|
+
@multifind07
|
35
|
+
Scenario: multifind07 - multifind all with no results
|
36
|
+
Given I navigate to the find test page
|
37
|
+
Then the user expects an error in a multi_find_all lookup
|
38
|
+
|
39
|
+
@multifind08
|
40
|
+
Scenario: multifind08 - multifind all with no results and no error
|
41
|
+
Given I navigate to the find test page
|
42
|
+
Then the user expects no error in a multi_find_all lookup
|
43
|
+
|
44
|
+
@multifind09
|
45
|
+
Scenario: multifind09 - multifind all natching all elements with no results
|
46
|
+
Given I navigate to the find test page
|
47
|
+
Then the user expects an error in a multi_find_all lookup matching all elements
|
48
|
+
|
49
|
+
@multifind10
|
50
|
+
Scenario: multifind10 - multifind all natching all elements with no error
|
51
|
+
Given I navigate to the find test page
|
52
|
+
Then the user expects no error in a multi_find_all lookup matching all elements
|
@@ -0,0 +1,35 @@
|
|
1
|
+
@screenshot @p
|
2
|
+
Feature: Screenshot
|
3
|
+
When I want to test the Lapis Lazuli library
|
4
|
+
I want to run a webserver with some test files
|
5
|
+
And execute the each library function searches for elements.
|
6
|
+
|
7
|
+
@screenshot_01
|
8
|
+
Scenario: screenshot_01 - Successfull scenario with screenshots
|
9
|
+
Given I navigate to the screenshot test page
|
10
|
+
When I take a screenshot
|
11
|
+
Then I take a screenshot
|
12
|
+
|
13
|
+
@screenshot_02
|
14
|
+
Scenario: screenshot_02 - Taking a screenshot on a failed scenario
|
15
|
+
Given I navigate to the screenshot test page
|
16
|
+
Then I fail this step
|
17
|
+
|
18
|
+
@screenshot_03
|
19
|
+
Scenario Outline: screenshot_03 - Successfull scenario outlines with screenshots
|
20
|
+
Given I navigate to the screenshot test page
|
21
|
+
When I take a screenshot
|
22
|
+
Then I take a screenshot
|
23
|
+
Examples:
|
24
|
+
| fails |
|
25
|
+
| failing once |
|
26
|
+
| failing twice |
|
27
|
+
|
28
|
+
@screenshot_04
|
29
|
+
Scenario Outline: screenshot_04 - Failing in a scenario outline
|
30
|
+
Given I navigate to the screenshot test page
|
31
|
+
Then I fail this step
|
32
|
+
Examples:
|
33
|
+
| fails |
|
34
|
+
| failing once |
|
35
|
+
| failing twice |
|
@@ -214,4 +214,12 @@ end
|
|
214
214
|
|
215
215
|
Given(/^I restart the browser to device setting "(.*?)"$/) do |device|
|
216
216
|
browser.restart :chrome, device: device
|
217
|
+
end
|
218
|
+
|
219
|
+
When(/^I take a screenshot$/) do
|
220
|
+
browser.take_screenshot
|
221
|
+
end
|
222
|
+
|
223
|
+
When(/^I fail this step$/) do
|
224
|
+
error 'This step fails because it is suppose to'
|
217
225
|
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
Given(/^the user expects a result in a multi_find lookup$/) do
|
2
|
+
elm = browser.multi_find(
|
3
|
+
:selectors => [
|
4
|
+
{:input => {:type => 'notexist'}},
|
5
|
+
{:like => [:a, :text, 'Link']}
|
6
|
+
]
|
7
|
+
)
|
8
|
+
unless elm.text == 'Rel Link'
|
9
|
+
error "Expected element with text `blog`, but received `#{elm.text}`"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Given(/^the user expects an error in a multi_find lookup$/) do
|
14
|
+
err = ''
|
15
|
+
begin
|
16
|
+
elm = browser.multi_find(
|
17
|
+
:selectors => [
|
18
|
+
{:input => {:type => 'notexist'}},
|
19
|
+
{:like => [:a, :id, 'notexist2']}
|
20
|
+
]
|
21
|
+
)
|
22
|
+
err = "Expected an error looking for elements with no results."
|
23
|
+
rescue RuntimeError => e
|
24
|
+
puts "Caught expected error: #{e.message}"
|
25
|
+
end
|
26
|
+
error err unless err.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
Given(/^the user expects no error in a multi_find lookup$/) do
|
30
|
+
elm = browser.multi_find(
|
31
|
+
:selectors => [
|
32
|
+
{:input => {:type => 'notexist'}},
|
33
|
+
{:like => [:a, :id, 'notexist2']}
|
34
|
+
],
|
35
|
+
:throw => false
|
36
|
+
)
|
37
|
+
unless elm.nil?
|
38
|
+
error "Expected the result to be nil."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Given(/^the user expects 8 results in a multi_find_all lookup$/) do
|
43
|
+
elm = browser.multi_find_all(
|
44
|
+
:selectors => [
|
45
|
+
{:like => [:div, :name, 'count']},
|
46
|
+
{:like => [:a, :text, 'Link']}
|
47
|
+
]
|
48
|
+
)
|
49
|
+
unless elm.length == 8
|
50
|
+
error "Expected 2 elements, but received `#{elm.length}`"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Given(/^the user expects 1 results in a multi_find_all lookup$/) do
|
55
|
+
elm = browser.multi_find_all(
|
56
|
+
:selectors => [
|
57
|
+
{:input => {:type => 'notexist'}},
|
58
|
+
{:like => [:a, :text, 'Link']}
|
59
|
+
]
|
60
|
+
)
|
61
|
+
unless elm[0].text == 'Rel Link'
|
62
|
+
error "Expected element with text `blog`, but received `#{elm.text}`"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
Given(/^the user expects 5 existing results in a multi_find_all lookup$$/) do
|
67
|
+
elm = browser.multi_find_all(
|
68
|
+
:selectors => [
|
69
|
+
{:like => [:a, :id, 'notexists']},
|
70
|
+
{:like => [:div, :name, 'count'], :filter_by => :exists?},
|
71
|
+
]
|
72
|
+
)
|
73
|
+
unless elm.length == 5
|
74
|
+
error "Expected 5 elements, but received `#{elm.length}`"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
Given(/^the user expects an error in a multi_find_all lookup$/) do
|
79
|
+
err = ''
|
80
|
+
begin
|
81
|
+
elm = browser.multi_find_all(
|
82
|
+
:selectors => [
|
83
|
+
{:input => {:type => 'notexist'}},
|
84
|
+
{:like => [:a, :id, 'notexist2']}
|
85
|
+
]
|
86
|
+
)
|
87
|
+
err = "Expected an error looking for elements with no results."
|
88
|
+
rescue RuntimeError => e
|
89
|
+
puts "Caught expected error: #{e.message}"
|
90
|
+
end
|
91
|
+
error err unless err.empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
Given(/^the user expects no error in a multi_find_all lookup$/) do
|
95
|
+
elm = browser.multi_find_all(
|
96
|
+
:selectors => [
|
97
|
+
{:input => {:type => 'notexist'}},
|
98
|
+
{:like => [:a, :id, 'notexist2']}
|
99
|
+
],
|
100
|
+
:throw => false
|
101
|
+
)
|
102
|
+
unless elm.length == 0
|
103
|
+
error "Expected to receive 0 results."
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
Given(/^the user expects an error in a multi_find_all lookup matching all elements$/) do
|
108
|
+
err = ''
|
109
|
+
begin
|
110
|
+
elm = browser.multi_find_all(
|
111
|
+
:selectors => [
|
112
|
+
{:input => {:type => 'texta'}},
|
113
|
+
{:like => [:a, :text, 'Link']}
|
114
|
+
],
|
115
|
+
:mode => :match_all
|
116
|
+
)
|
117
|
+
err = "Expected an error matching all elements with results."
|
118
|
+
rescue RuntimeError => e
|
119
|
+
puts "Caught expected error: #{e.message}"
|
120
|
+
end
|
121
|
+
error err unless err.empty?
|
122
|
+
end
|
123
|
+
Given(/^the user expects no error in a multi_find_all lookup matching all elements$/) do
|
124
|
+
|
125
|
+
elm = browser.multi_find_all(
|
126
|
+
:selectors => [
|
127
|
+
{:input => {:type => 'texta'}},
|
128
|
+
{:like => [:a, :text, 'Link']}
|
129
|
+
],
|
130
|
+
:mode => :match_all,
|
131
|
+
:throw => false
|
132
|
+
)
|
133
|
+
unless elm.length == 0
|
134
|
+
error "Expected to receive 0 results."
|
135
|
+
end
|
136
|
+
end
|
@@ -67,6 +67,7 @@ Then(/(first|last|random|[0-9]+[a-z]+) (.*) should (not )?be present$/) do |inde
|
|
67
67
|
options[type.to_sym] = {}
|
68
68
|
# Pick the correct one
|
69
69
|
options[:pick] = pick
|
70
|
+
options[:filter_by] = :exists?
|
70
71
|
# Execute the find
|
71
72
|
type_element = browser.find(options)
|
72
73
|
# Find all
|
@@ -76,7 +77,7 @@ Then(/(first|last|random|[0-9]+[a-z]+) (.*) should (not )?be present$/) do |inde
|
|
76
77
|
all_present = browser.find_all(options)
|
77
78
|
|
78
79
|
if hidden and type_element.present?
|
79
|
-
error("Hidden element is visible")
|
80
|
+
error("Hidden element is visible using selectors: #{options}")
|
80
81
|
elsif not hidden and not type_element.present?
|
81
82
|
error("Element is hidden")
|
82
83
|
elsif hidden and not type_element.present? and
|
@@ -94,10 +95,9 @@ Then(/^within (\d+) seconds I should see "([^"]+?)"( disappear)?$/) do |timeout,
|
|
94
95
|
else
|
95
96
|
condition = :until
|
96
97
|
end
|
97
|
-
|
98
98
|
browser.wait(
|
99
99
|
:timeout => timeout,
|
100
|
-
:
|
100
|
+
:html => /#{text}/,
|
101
101
|
:condition => condition,
|
102
102
|
:groups => ["wait #{condition.to_s}"]
|
103
103
|
)
|
@@ -215,8 +215,7 @@ Then(/^I expect a (\d+) status code$/) do |expected|
|
|
215
215
|
scenario.check_browser_errors = false
|
216
216
|
elsif browser.get_http_status != expected
|
217
217
|
error(
|
218
|
-
:message => "Incorrect status code: #{browser.get_http_status}"
|
219
|
-
:groups => ["error"]
|
218
|
+
:message => "Incorrect status code: #{browser.get_http_status}"
|
220
219
|
)
|
221
220
|
end
|
222
221
|
end
|
@@ -234,13 +233,13 @@ end
|
|
234
233
|
|
235
234
|
Then(/^the firefox browser named "(.*?)" has a profile$/) do |name|
|
236
235
|
if scenario.storage.has? name
|
237
|
-
|
238
|
-
if
|
239
|
-
if
|
236
|
+
b = scenario.storage.get name
|
237
|
+
if b.browser_name == "remote"
|
238
|
+
if b.driver.capabilities.firefox_profile.nil?
|
240
239
|
raise "Remote Firefox Profile is not set"
|
241
240
|
end
|
242
241
|
else
|
243
|
-
if
|
242
|
+
if !b.optional_data.has_key? "profile" and !b.optional_data.has_key? :profile
|
244
243
|
raise "No profile found in the optional data"
|
245
244
|
end
|
246
245
|
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
|
3
|
+
<html lang="en">
|
4
|
+
<head>
|
5
|
+
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<h1>Screenshot test page</h1>
|
9
|
+
|
10
|
+
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam,
|
11
|
+
feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies
|
12
|
+
mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat
|
13
|
+
wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros
|
14
|
+
ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.
|
15
|
+
Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam
|
16
|
+
erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
|
17
|
+
<ul>
|
18
|
+
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
|
19
|
+
<li>Aliquam tincidunt mauris eu risus.</li>
|
20
|
+
<li>Vestibulum auctor dapibus neque.</li>
|
21
|
+
</ul>
|
22
|
+
<h1>HTML Ipsum Presents</h1>
|
23
|
+
|
24
|
+
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas.
|
25
|
+
Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas
|
26
|
+
semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien
|
27
|
+
ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi.
|
28
|
+
Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a
|
29
|
+
href="#">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p>
|
30
|
+
|
31
|
+
<h2>Header Level 2</h2>
|
32
|
+
|
33
|
+
<ol>
|
34
|
+
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
|
35
|
+
<li>Aliquam tincidunt mauris eu risus.</li>
|
36
|
+
</ol>
|
37
|
+
|
38
|
+
<blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet
|
39
|
+
congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus
|
40
|
+
est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote>
|
41
|
+
|
42
|
+
<h3>Header Level 3</h3>
|
43
|
+
|
44
|
+
<ul>
|
45
|
+
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
|
46
|
+
<li>Aliquam tincidunt mauris eu risus.</li>
|
47
|
+
</ul>
|
48
|
+
|
49
|
+
<pre><code>
|
50
|
+
#header h1 a {
|
51
|
+
display: block;
|
52
|
+
width: 300px;
|
53
|
+
height: 80px;
|
54
|
+
}
|
55
|
+
</code></pre>
|
56
|
+
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam,
|
57
|
+
feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies
|
58
|
+
mi vitae est. Mauris placerat eleifend leo.</p>
|
59
|
+
<ul>
|
60
|
+
<li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed
|
61
|
+
arcu. Cras consequat.
|
62
|
+
</li>
|
63
|
+
<li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam
|
64
|
+
erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.
|
65
|
+
</li>
|
66
|
+
<li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus.
|
67
|
+
Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.
|
68
|
+
</li>
|
69
|
+
<li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.
|
70
|
+
</li>
|
71
|
+
</ul>
|
72
|
+
<form action="#" method="post">
|
73
|
+
<div>
|
74
|
+
<label for="name">Text Input:</label>
|
75
|
+
<input type="text" name="name" id="name" value="" tabindex="1"/>
|
76
|
+
</div>
|
77
|
+
|
78
|
+
<div>
|
79
|
+
<h4>Radio Button Choice</h4>
|
80
|
+
|
81
|
+
<label for="radio-choice-1">Choice 1</label>
|
82
|
+
<input type="radio" name="radio-choice-1" id="radio-choice-1" tabindex="2" value="choice-1"/>
|
83
|
+
|
84
|
+
<label for="radio-choice-2">Choice 2</label>
|
85
|
+
<input type="radio" name="radio-choice-2" id="radio-choice-2" tabindex="3" value="choice-2"/>
|
86
|
+
</div>
|
87
|
+
|
88
|
+
<div>
|
89
|
+
<label for="select-choice">Select Dropdown Choice:</label>
|
90
|
+
<select name="select-choice" id="select-choice">
|
91
|
+
<option value="Choice 1">Choice 1</option>
|
92
|
+
<option value="Choice 2">Choice 2</option>
|
93
|
+
<option value="Choice 3">Choice 3</option>
|
94
|
+
</select>
|
95
|
+
</div>
|
96
|
+
|
97
|
+
<div>
|
98
|
+
<label for="textarea">Textarea:</label>
|
99
|
+
<textarea cols="40" rows="8" name="textarea" id="textarea"></textarea>
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<div>
|
103
|
+
<label for="checkbox">Checkbox:</label>
|
104
|
+
<input type="checkbox" name="checkbox" id="checkbox"/>
|
105
|
+
</div>
|
106
|
+
|
107
|
+
<div>
|
108
|
+
<input type="submit" value="Submit"/>
|
109
|
+
</div>
|
110
|
+
</form>
|
111
|
+
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
|
112
|
+
<ol>
|
113
|
+
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
|
114
|
+
<li>Aliquam tincidunt mauris eu risus.</li>
|
115
|
+
<li>Vestibulum auctor dapibus neque.</li>
|
116
|
+
</ol>
|
117
|
+
<dl>
|
118
|
+
<dt>Definition list</dt>
|
119
|
+
<dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
120
|
+
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
121
|
+
commodo consequat.
|
122
|
+
</dd>
|
123
|
+
<dt>Lorem ipsum dolor sit amet</dt>
|
124
|
+
<dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
|
125
|
+
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
126
|
+
commodo consequat.
|
127
|
+
</dd>
|
128
|
+
</dl>
|
129
|
+
<nav>
|
130
|
+
<ul>
|
131
|
+
<li><a href="#nowhere" title="Lorum ipsum dolor sit amet">Lorem</a></li>
|
132
|
+
<li><a href="#nowhere" title="Aliquam tincidunt mauris eu risus">Aliquam</a></li>
|
133
|
+
<li><a href="#nowhere" title="Morbi in sem quis dui placerat ornare">Morbi</a></li>
|
134
|
+
<li><a href="#nowhere" title="Praesent dapibus, neque id cursus faucibus">Praesent</a></li>
|
135
|
+
<li><a href="#nowhere" title="Pellentesque fermentum dolor">Pellentesque</a></li>
|
136
|
+
</ul>
|
137
|
+
</nav>
|
138
|
+
<nav>
|
139
|
+
<ul>
|
140
|
+
<li><a href="#">Home</a></li>
|
141
|
+
<li><a href="#">About</a></li>
|
142
|
+
<li><a href="#">Clients</a></li>
|
143
|
+
<li><a href="#">Contact Us</a></li>
|
144
|
+
</ul>
|
145
|
+
</nav>
|
146
|
+
</body>
|
147
|
+
</html>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lapis_lazuli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Onno Steenbergen
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2017-
|
14
|
+
date: 2017-07-14 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -277,7 +277,10 @@ files:
|
|
277
277
|
- test/features/find.feature
|
278
278
|
- test/features/har.feature
|
279
279
|
- test/features/modules.feature
|
280
|
+
- test/features/multifind.feature
|
281
|
+
- test/features/screenshot.feature
|
280
282
|
- test/features/step_definitions/interaction_steps.rb
|
283
|
+
- test/features/step_definitions/multifind_steps.rb
|
281
284
|
- test/features/step_definitions/validation_steps.rb
|
282
285
|
- test/features/support/env.rb
|
283
286
|
- test/features/text_field.feature
|
@@ -289,6 +292,7 @@ files:
|
|
289
292
|
- test/server/www/error_html.html
|
290
293
|
- test/server/www/find.html
|
291
294
|
- test/server/www/javascript_error.html
|
295
|
+
- test/server/www/screenshot.html
|
292
296
|
- test/server/www/text_fields.html
|
293
297
|
- test/server/www/timing.html
|
294
298
|
- test/server/www/xpath.html
|
@@ -312,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
312
316
|
version: '0'
|
313
317
|
requirements: []
|
314
318
|
rubyforge_project:
|
315
|
-
rubygems_version: 2.6.
|
319
|
+
rubygems_version: 2.6.12
|
316
320
|
signing_key:
|
317
321
|
specification_version: 4
|
318
322
|
summary: Cucumber helper functions and scaffolding for easier test automation suite
|
@@ -334,7 +338,10 @@ test_files:
|
|
334
338
|
- test/features/find.feature
|
335
339
|
- test/features/har.feature
|
336
340
|
- test/features/modules.feature
|
341
|
+
- test/features/multifind.feature
|
342
|
+
- test/features/screenshot.feature
|
337
343
|
- test/features/step_definitions/interaction_steps.rb
|
344
|
+
- test/features/step_definitions/multifind_steps.rb
|
338
345
|
- test/features/step_definitions/validation_steps.rb
|
339
346
|
- test/features/support/env.rb
|
340
347
|
- test/features/text_field.feature
|
@@ -346,6 +353,7 @@ test_files:
|
|
346
353
|
- test/server/www/error_html.html
|
347
354
|
- test/server/www/find.html
|
348
355
|
- test/server/www/javascript_error.html
|
356
|
+
- test/server/www/screenshot.html
|
349
357
|
- test/server/www/text_fields.html
|
350
358
|
- test/server/www/timing.html
|
351
359
|
- test/server/www/xpath.html
|