lapis_lazuli 2.0.1 → 2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lapis_lazuli.gemspec +3 -2
- data/lib/lapis_lazuli/browser.rb +36 -60
- data/lib/lapis_lazuli/browser/error.rb +89 -62
- data/lib/lapis_lazuli/generators/cucumber/template/README.md +2 -0
- data/lib/lapis_lazuli/generators/cucumber/template/config/config.yml +5 -20
- data/lib/lapis_lazuli/generators/cucumber/template/config/cucumber.yml +42 -13
- data/lib/lapis_lazuli/generators/cucumber/template/config/users.yml +21 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/1_basic.feature +42 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/2_account.feature +38 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/3_todo_list.feature +23 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/helpers/authentication_helper.rb +122 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/helpers/navigation_helper.rb +64 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/helpers/registration_helper.rb +93 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/helpers/user_helper.rb +74 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/account_steps.rb +60 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/basic_steps.rb +65 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/todo_steps.rb +27 -0
- data/lib/lapis_lazuli/generators/cucumber/template/features/support/env.rb +3 -2
- data/lib/lapis_lazuli/options.rb +2 -1
- data/lib/lapis_lazuli/version.rb +1 -1
- data/lib/lapis_lazuli/world/config.rb +348 -334
- data/lib/lapis_lazuli/world/hooks.rb +85 -84
- data/lib/lapis_lazuli/world/logging.rb +1 -1
- data/test/config/config.yml +7 -6
- data/test/config/cucumber.yml +6 -8
- data/test/features/bindings.feature +1 -1
- data/test/features/browser.feature +1 -1
- data/test/features/step_definitions/interaction_steps.rb +5 -2
- data/test/features/step_definitions/validation_steps.rb +2 -2
- data/test/features/support/env.rb +22 -1
- data/test/results/latest_results.json +0 -0
- metadata +49 -16
- data/lib/lapis_lazuli/generators/cucumber/template/features/account.feature +0 -26
- data/lib/lapis_lazuli/generators/cucumber/template/features/example.feature +0 -30
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/interaction_steps.rb +0 -165
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/precondition_steps.rb +0 -63
- data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/validation_steps.rb +0 -67
- data/lib/lapis_lazuli/generators/cucumber/template/features/support/functions.rb +0 -68
@@ -1,26 +0,0 @@
|
|
1
|
-
@account
|
2
|
-
Feature: User accounts
|
3
|
-
This feature will make sure the user account functionality is working as expected
|
4
|
-
By checking registration, login and logout functionality
|
5
|
-
|
6
|
-
# This is a best practise example. Please note the following
|
7
|
-
# By defining a register, log-in and log-out state, we can easily re-use all these preconditions
|
8
|
-
# All the scenario's aren't completed, but it should be easy to implement it into your own project.
|
9
|
-
|
10
|
-
@account01 @log_in #@pause # You can add @pause to have a break between every step.
|
11
|
-
Scenario: account01 - Logging in
|
12
|
-
Given the user is logged out
|
13
|
-
When "default-user" logs in
|
14
|
-
Then the page should display as logged in state
|
15
|
-
|
16
|
-
@account02 @log_out
|
17
|
-
Scenario: account01 - Logging out
|
18
|
-
Given "default-user" is logged in
|
19
|
-
When the user clicks on the logout button
|
20
|
-
Then the page should display as logged out state
|
21
|
-
|
22
|
-
@account03 @registration
|
23
|
-
Scenario: account03 - Registation
|
24
|
-
Given the user is logged out
|
25
|
-
When "random-user" registers for a new account
|
26
|
-
Then the page should display as logged in state
|
@@ -1,30 +0,0 @@
|
|
1
|
-
@example @p
|
2
|
-
Feature: Example Feature
|
3
|
-
When I want to learn how to make test cases
|
4
|
-
As a user of the test automation tool
|
5
|
-
I want to run and adjust the tests below
|
6
|
-
|
7
|
-
@example01
|
8
|
-
Scenario: example01 - Spritecloud search
|
9
|
-
Given the user navigates to "blog"
|
10
|
-
When the user searches for "lapis lazuli"
|
11
|
-
Then text "Open Source" should display
|
12
|
-
|
13
|
-
@example02
|
14
|
-
Scenario: example02 - Going to a search result
|
15
|
-
Given the user has searched for "lapis lazuli" on "blog"
|
16
|
-
When the user clicks on link "/announcing-lapislazuli/"
|
17
|
-
Then text "Let's talk about testing" should display
|
18
|
-
|
19
|
-
@example03
|
20
|
-
Scenario Outline: example03 - checking multiple pages for the logo
|
21
|
-
Given the user navigates to "<page>"
|
22
|
-
When the user clicks on the spritecloud logo
|
23
|
-
Then the user should be on page "home"
|
24
|
-
Scenarios:
|
25
|
-
| page |
|
26
|
-
| blog |
|
27
|
-
| home |
|
28
|
-
| about-us |
|
29
|
-
| testing |
|
30
|
-
| functional-testing |
|
data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/interaction_steps.rb
DELETED
@@ -1,165 +0,0 @@
|
|
1
|
-
################################################################################
|
2
|
-
# Copyright <%= config[:year] %> spriteCloud B.V. All rights reserved.
|
3
|
-
# Generated by LapisLazuli, version <%= config[:lapis_lazuli][:version] %>
|
4
|
-
# Author: "<%= config[:user] %>" <<%= config[:email] %>>
|
5
|
-
|
6
|
-
# interactions_steps.rb is used to interact with elements on the page.
|
7
|
-
|
8
|
-
Given(/^the user navigates to "(.*?)"$/) do |page|
|
9
|
-
# Get the value of the configuration (see /config/config.yml)
|
10
|
-
|
11
|
-
# First grab the root URL defined in the config
|
12
|
-
url = env('pages.root')
|
13
|
-
# Then add the page specific part to the URL
|
14
|
-
url += env("pages.#{page}")
|
15
|
-
|
16
|
-
# Go to the URL
|
17
|
-
browser.goto url
|
18
|
-
end
|
19
|
-
|
20
|
-
Given(/^the user navigates to the "(.*?)" page$/) do |page|
|
21
|
-
# Get the value of the configuration (see /config/config.yml)
|
22
|
-
url = env("#{page}")
|
23
|
-
|
24
|
-
# Go to the URL
|
25
|
-
browser.goto url
|
26
|
-
end
|
27
|
-
|
28
|
-
Given(/^the user searches for "(.*?)"$/) do |query|
|
29
|
-
# Get the input element
|
30
|
-
searchbox = browser.find(:text_field => {:name => "s"})
|
31
|
-
# Make sure the input field is empty
|
32
|
-
searchbox.clear rescue log.debug "Could not clear searchbox"
|
33
|
-
# Fill in the query
|
34
|
-
searchbox.send_keys(query)
|
35
|
-
# Press enter to submit the search
|
36
|
-
searchbox.send_keys(:enter)
|
37
|
-
end
|
38
|
-
|
39
|
-
When(/^the user clicks on link "(.*?)"$/) do |url|
|
40
|
-
# Search for the element that includes the expected text
|
41
|
-
browser.wait(
|
42
|
-
:like => {
|
43
|
-
:element => :a,
|
44
|
-
:attribute => :href,
|
45
|
-
:include => url
|
46
|
-
}
|
47
|
-
).click
|
48
|
-
end
|
49
|
-
|
50
|
-
When(/^the user clicks on the spritecloud logo$/) do
|
51
|
-
# Search for the logo
|
52
|
-
logo = browser.find(
|
53
|
-
:like => [:img, :id, 'logo'],
|
54
|
-
:message => 'Unable to find the logo on this page.'
|
55
|
-
)
|
56
|
-
# And click the logo
|
57
|
-
logo.click
|
58
|
-
end
|
59
|
-
|
60
|
-
# A step definition is a regex, to learn more about this go to http://rubular.com/
|
61
|
-
# The following step definition accepts both:
|
62
|
-
# - the user logs in > will use the last stored user data
|
63
|
-
# - "user-x" logs in > will load user data from config.yml
|
64
|
-
When(/^"?(.*?|the user)"? logs in$/) do |user_tag|
|
65
|
-
if user_tag != 'the user'
|
66
|
-
# Set the user data
|
67
|
-
set_user_data(user_tag)
|
68
|
-
end
|
69
|
-
# Fill in the user form
|
70
|
-
browser.find(
|
71
|
-
:like => [:input, :id, 'login-username']
|
72
|
-
).set(get_user_data('username'))
|
73
|
-
browser.find(
|
74
|
-
:like => [:input, :id, 'login-password']
|
75
|
-
).set(get_user_data('password'))
|
76
|
-
|
77
|
-
# Press the submit button
|
78
|
-
browser.find(
|
79
|
-
:like => [:button, :id, 'button-login']
|
80
|
-
).click
|
81
|
-
end
|
82
|
-
|
83
|
-
When(/^the user clicks on the logout button$/) do
|
84
|
-
# pending # This is an example
|
85
|
-
|
86
|
-
# First get the header to use as a context for the logout button
|
87
|
-
header = browser.wait(:like => [:nav, :class, 'navbar-fixed-top'])
|
88
|
-
|
89
|
-
# Then click the logout button (in this case, first a drop down needs to be clicked, before the logout button shows)
|
90
|
-
browser.find(
|
91
|
-
:like => [:a, :id, 'user_dropdown'],
|
92
|
-
:context => header,
|
93
|
-
:message => 'Unable to click on the user icon'
|
94
|
-
).click
|
95
|
-
dropdown = browser.wait(
|
96
|
-
:like => [:ul, :class, 'dropdown-menu'],
|
97
|
-
:timeout => 5,
|
98
|
-
:message => 'The user dropdown didn`t become present.'
|
99
|
-
)
|
100
|
-
browser.find(
|
101
|
-
:like => [:a, :id, 'link-logout'],
|
102
|
-
:context => dropdown,
|
103
|
-
:error => 'Failed to click the logout button.'
|
104
|
-
).click
|
105
|
-
end
|
106
|
-
|
107
|
-
When(/^"(.*?)" registers for a new account$/) do |user_tag|
|
108
|
-
# pending # Write code here that turns the phrase above into concrete actions
|
109
|
-
|
110
|
-
# Set the user data
|
111
|
-
set_user_data(user_tag)
|
112
|
-
|
113
|
-
# Go to the registration page
|
114
|
-
step 'the user navigates to the "training-page" page'
|
115
|
-
browser.find(:like => [:button, :id, 'button-register']).click
|
116
|
-
|
117
|
-
# Fill in the form
|
118
|
-
|
119
|
-
# Get the form container and use it as a context to find the fields
|
120
|
-
form = browser.wait(:like => [:form, :id, 'form-register'])
|
121
|
-
|
122
|
-
# Fill in the details
|
123
|
-
browser.find(:element => {:name => 'username'}, :context => form).set get_user_data('username')
|
124
|
-
browser.find(:element => {:name => 'password'}, :context => form).set get_user_data('password')
|
125
|
-
|
126
|
-
# Select gender
|
127
|
-
browser.find(
|
128
|
-
:label => {:text => /#{get_user_data('gender')}/i},
|
129
|
-
:context => form,
|
130
|
-
:message => "Unable to find gender `#{get_user_data('gender')}`, are you sure it's an option to select??"
|
131
|
-
).click
|
132
|
-
|
133
|
-
# Select experiences from the multi-select list
|
134
|
-
multi_selector = browser.find(:like => [:select, :id, "register-experience"], :context => form)
|
135
|
-
experiences = get_user_data('experience')
|
136
|
-
# Experiences is a list of words comma separated, EG `Ruby,Cucumber,Watir`
|
137
|
-
# The following function will cut text at every comma, and loop trough every separate word
|
138
|
-
experiences.split(',').each do |exp|
|
139
|
-
option = browser.find(
|
140
|
-
:option => {:value => /#{exp}/i},
|
141
|
-
:context => multi_selector
|
142
|
-
)
|
143
|
-
option.click
|
144
|
-
end
|
145
|
-
|
146
|
-
# Fill in the biagraphy
|
147
|
-
browser.find(
|
148
|
-
:like => [:textarea, :id, 'register-bio']
|
149
|
-
).send_keys(get_user_data('biography'))
|
150
|
-
|
151
|
-
# Click the accept policy checkbox
|
152
|
-
browser.find(:like => [:input, :id, 'register-complete-all']).click
|
153
|
-
|
154
|
-
# Press the submit button
|
155
|
-
browser.find(:button => {:id => 'button-save'}).click
|
156
|
-
|
157
|
-
# Wait for the success message to display
|
158
|
-
browser.wait(
|
159
|
-
:like => [:div, :class, 'alert-success'],
|
160
|
-
:message => 'The successfully registered message did not display.'
|
161
|
-
)
|
162
|
-
|
163
|
-
# The website we're testing on, doesn't log in the user automatically. So let's trigger that step manually
|
164
|
-
step 'the user logs in'
|
165
|
-
end
|
data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/precondition_steps.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
################################################################################
|
2
|
-
# Copyright <%= config[:year] %> spriteCloud B.V. All rights reserved.
|
3
|
-
# Generated by LapisLazuli, version <%= config[:lapis_lazuli][:version] %>
|
4
|
-
# Author: "<%= config[:user] %>" <<%= config[:email] %>>
|
5
|
-
|
6
|
-
# precondition_steps.rb is used to define steps that contain multiple steps to come to a certain start of a scenrario.
|
7
|
-
# For example: "Given the user is logged in" will contain all steps done before logging in
|
8
|
-
|
9
|
-
Given(/^the user has searched for "(.*?)" on "(.*?)"$/) do |query, page|
|
10
|
-
# Run step to go to page
|
11
|
-
step "the user navigates to \"#{page}\""
|
12
|
-
# Run step to search
|
13
|
-
step "the user searches for \"#{query}\""
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
Given(/^the user is logged out$/) do
|
18
|
-
# In this step we want to make sure that the user is not logged in.
|
19
|
-
# If the user is not logged in, then this step does nothing, else it will trigger the logout step.
|
20
|
-
|
21
|
-
# Make this step independent by going to the homepage
|
22
|
-
step 'the user navigates to the "training-page" page'
|
23
|
-
|
24
|
-
# Check if the user is already logged in
|
25
|
-
loggedin = browser.find(
|
26
|
-
:like => [:img, :id, 'user-gravatar'],
|
27
|
-
:throw => false # This will prevent that the lookup will thow an error if it fails
|
28
|
-
)
|
29
|
-
if !loggedin.nil?
|
30
|
-
# Then try clicking the logout button
|
31
|
-
begin
|
32
|
-
step 'the user clicks on the logout button'
|
33
|
-
rescue Exception => e
|
34
|
-
# Ignoring the error, since it probably means we're already logged out.
|
35
|
-
log.debug "Logout failed, so I should already be logged out: #{e}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# And confirm we've successfully logged out
|
40
|
-
step 'the page should display as logged out state'
|
41
|
-
end
|
42
|
-
|
43
|
-
Given(/^(".*?"|the user) is logged in$/) do |user_tag|
|
44
|
-
# First, make sure we're not logged into another account
|
45
|
-
step 'the user is logged out'
|
46
|
-
# Note: This could be more efficient, often you're already logged in with the correct user.
|
47
|
-
# So a different solution would be to check if the correct user is already logged in:
|
48
|
-
# set_user_data(user_tag)
|
49
|
-
# logged_in? = browser.find(
|
50
|
-
# :span => {:text => get_user_data('username')},
|
51
|
-
# :throw => false
|
52
|
-
# )
|
53
|
-
# if logged_in? skip the rest
|
54
|
-
|
55
|
-
# Then follow the login steps
|
56
|
-
step "#{user_tag} logs in"
|
57
|
-
|
58
|
-
# And confirm the login was successful
|
59
|
-
step 'the page should display as logged in state'
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
|
data/lib/lapis_lazuli/generators/cucumber/template/features/step_definitions/validation_steps.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
################################################################################
|
2
|
-
# Copyright <%= config[:year] %> spriteCloud B.V. All rights reserved.
|
3
|
-
# Generated by LapisLazuli, version <%= config[:lapis_lazuli][:version] %>
|
4
|
-
# Author: "<%= config[:user] %>" <<%= config[:email] %>>
|
5
|
-
|
6
|
-
# validation_steps.rb is used to confirm that certain elements are displayed on the page.
|
7
|
-
|
8
|
-
Then(/^text "([^"]*)" should display$/) do |string|
|
9
|
-
# Note: The following is *really* slow, as it'll apply the regex to all
|
10
|
-
# elements in the page, one after the other. Of course, if any element
|
11
|
-
# includes the regex, all its parent elements also will, so you have
|
12
|
-
# tons of matches to process.
|
13
|
-
#
|
14
|
-
# browser.wait(:text => /#{string}/i)
|
15
|
-
|
16
|
-
# Instead, you will want to search only the root element for some
|
17
|
-
# text, e.g.
|
18
|
-
#
|
19
|
-
# browser.wait(:html => {:text => /#{string}/i})
|
20
|
-
|
21
|
-
# There's a shortcut for that in find/wait:
|
22
|
-
browser.wait(:html => /#{string}/i)
|
23
|
-
end
|
24
|
-
|
25
|
-
Then(/^the user should be on page "(.*?)"$/) do |page|
|
26
|
-
# Get the expected url
|
27
|
-
expected_url = env('pages.root')
|
28
|
-
expected_url += env("pages.#{page}")
|
29
|
-
|
30
|
-
# A custom loop that waits 5 seconds until the expected_url is the same as the current url
|
31
|
-
start = Time.now
|
32
|
-
while browser.url != expected_url
|
33
|
-
break if (Time.now - start).to_i >= 5
|
34
|
-
sleep(0.1)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Check if they are the same
|
38
|
-
if browser.url != expected_url
|
39
|
-
error("The current URL and expected URL were not the same: \n Current: #{browser.url}\n Expected: #{expected_url}")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
Then(/^the page should display as logged (in|out) state$/) do |logged|
|
45
|
-
# pending # Write code here that turns the phrase above into concrete actions
|
46
|
-
|
47
|
-
# Adjust variable for checking logged in or logged out state.
|
48
|
-
if logged == 'in'
|
49
|
-
condition = :until
|
50
|
-
message = 'Unable to find profile picture, the user wasnt logged in successfully'
|
51
|
-
elsif logged == 'out'
|
52
|
-
condition = :while
|
53
|
-
message = 'The profile picture is present, indicating that the user did not log out successfully'
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
# Try to find a way to confirm that a user is logged out.
|
58
|
-
# Easiest way is to a reversed check on an element that is only present when you're logged in
|
59
|
-
# For example, the profile picture
|
60
|
-
browser.wait(
|
61
|
-
:img => {:class => 'user-gravatar'},
|
62
|
-
:condition => condition,
|
63
|
-
:timeout => 5,
|
64
|
-
:message => message
|
65
|
-
)
|
66
|
-
# Lapis lazuli will automatically create a screenshot if this step fails.
|
67
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# Sometimes you're repeating a piece of code over and over again.
|
2
|
-
# At that point you should consider making it a function.
|
3
|
-
|
4
|
-
# Define a the user data to use.
|
5
|
-
def set_user_data(data)
|
6
|
-
# Load the user data from the configuration file
|
7
|
-
user_data = config("users.#{data}")
|
8
|
-
|
9
|
-
# Replace all random and time values in the data
|
10
|
-
user_data = replace_hash_constants(user_data)
|
11
|
-
|
12
|
-
# Put it in the global variable
|
13
|
-
$USER_DATA = user_data
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
# Get the data for the requested field.
|
18
|
-
def get_user_data(field)
|
19
|
-
# Make sure the user data is set before this function was called.
|
20
|
-
if $USER_DATA.nil?
|
21
|
-
error "No user data was set when get_user_data() was called for #{field}."
|
22
|
-
end
|
23
|
-
# Check if the specifically requested field is defined
|
24
|
-
if $USER_DATA[field].nil?
|
25
|
-
error "The requested user data `#{field}` does not exist. Are you sure it's defined in ./config/config.yml ?"
|
26
|
-
end
|
27
|
-
# Return te requested data
|
28
|
-
return $USER_DATA[field]
|
29
|
-
end
|
30
|
-
|
31
|
-
# Replace random or time values of a complete hash
|
32
|
-
def replace_hash_constants(hash)
|
33
|
-
if hash.respond_to? :each
|
34
|
-
new_hash = {}
|
35
|
-
hash.each do |key, value|
|
36
|
-
new_hash[key] = replace_constants(value)
|
37
|
-
end
|
38
|
-
else
|
39
|
-
new_hash = replace_constants(hash)
|
40
|
-
end
|
41
|
-
return new_hash
|
42
|
-
end
|
43
|
-
|
44
|
-
# replace certain constants in a string, for example '_TIMESTAMP_' becomes '154875631'
|
45
|
-
def replace_constants(value)
|
46
|
-
epoch = Time.now.to_i
|
47
|
-
alpha = number_to_letter(epoch)
|
48
|
-
timestamp = Time.now.strftime("D%Y-%M-%d-T%H-%M-%S")
|
49
|
-
value = value.to_s
|
50
|
-
old_val = value
|
51
|
-
value = value.sub('_RAND_', epoch.to_s)
|
52
|
-
value = value.sub('_TIMESTAMP_', timestamp)
|
53
|
-
value = value.sub('_RAND-ALPHA_', alpha)
|
54
|
-
unless value == old_val
|
55
|
-
log.debug "#{old_val} > #{value}"
|
56
|
-
end
|
57
|
-
return value
|
58
|
-
end
|
59
|
-
|
60
|
-
def number_to_letter(numbers)
|
61
|
-
num_string = numbers.to_s
|
62
|
-
alpha26 = ("a".."j").to_a
|
63
|
-
letters = ''
|
64
|
-
num_string.scan(/./).each do |number|
|
65
|
-
letters += alpha26[number.to_i]
|
66
|
-
end
|
67
|
-
return letters
|
68
|
-
end
|