lapis_lazuli 2.0.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/lapis_lazuli.gemspec +10 -8
- data/lib/lapis_lazuli/api.rb +1 -1
- data/lib/lapis_lazuli/argparse.rb +1 -1
- data/lib/lapis_lazuli/browser.rb +37 -61
- data/lib/lapis_lazuli/browser/error.rb +89 -62
- data/lib/lapis_lazuli/browser/find.rb +1 -2
- data/lib/lapis_lazuli/cli.rb +1 -1
- data/lib/lapis_lazuli/cucumber.rb +1 -1
- data/lib/lapis_lazuli/generators/cucumber.rb +1 -1
- data/lib/lapis_lazuli/generators/cucumber/template/README.md +2 -0
- data/lib/lapis_lazuli/generators/cucumber/template/config/config.yml +6 -21
- 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 +49 -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 +102 -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 +70 -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/generic/xpath.rb +1 -1
- data/lib/lapis_lazuli/options.rb +3 -2
- data/lib/lapis_lazuli/placeholders.rb +1 -1
- data/lib/lapis_lazuli/proxy.rb +1 -1
- data/lib/lapis_lazuli/runtime.rb +1 -1
- data/lib/lapis_lazuli/scenario.rb +1 -1
- data/lib/lapis_lazuli/storage.rb +1 -1
- data/lib/lapis_lazuli/version.rb +2 -2
- data/lib/lapis_lazuli/versions.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/Gemfile +2 -16
- 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 +21 -1
- data/test/results/latest_results.json +0 -0
- metadata +74 -28
- 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
@@ -24,39 +24,24 @@ error_strings:
|
|
24
24
|
################################################################################
|
25
25
|
# Environment specific variables
|
26
26
|
test:
|
27
|
+
root: http://username:password@test.spritecloud.com #Not an existing page, note the username/password user inside the URL
|
27
28
|
pages:
|
28
|
-
root: http://username:password@test.spritecloud.com #Not an existing page, note the username/password user inside the URL
|
29
29
|
home: /
|
30
30
|
about-us: /about-us/
|
31
31
|
|
32
32
|
uat:
|
33
|
+
root: http://username:password@uat.spritecloud.com #Not an existing page, note the username/password user inside the URL
|
33
34
|
pages:
|
34
|
-
root: http://username:password@uat.spritecloud.com #Not an existing page, note the username/password user inside the URL
|
35
35
|
home: /
|
36
36
|
about-us: /about-us/
|
37
37
|
|
38
38
|
production:
|
39
|
+
root: https://www.spritecloud.com
|
39
40
|
pages:
|
40
|
-
root: https://www.spritecloud.com
|
41
41
|
home: /
|
42
42
|
about-us: /about-us/
|
43
43
|
testing: /testing/
|
44
44
|
blog: /blog/
|
45
|
-
functional-testing: /testing/functional/
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# Different user variables
|
50
|
-
users:
|
51
|
-
default-user: # These are the default variable settings. If no setting was specified, these values will be used.
|
52
|
-
username: test
|
53
|
-
password: test
|
54
|
-
gender: 'Male'
|
55
|
-
experience: 'Ruby,Cucumber,HTML,XPath'
|
56
|
-
biography: 'Hello, I am Gijs, I am a Test Engineer for spriteCloud and I like to be lazy and let machines do my work'
|
57
|
-
random-user: # In ./features/support/functions.rb '_RAND-ALPHA_' is replaces for random alphanumeric characters.
|
58
|
-
username: usr_RAND-ALPHA_
|
59
|
-
password: test_RAND_
|
60
|
-
gender: 'Female'
|
61
|
-
experience: 'Ruby,Gherkin'
|
62
|
-
biography: 'Hello, I am a randomized user, today is _TIMESTAMP_ seconds after the existance of computers'
|
45
|
+
functional-testing: /testing/functional-testing/
|
46
|
+
jobs: /jobs
|
47
|
+
training-page: http://training-page.testautomation.info/#
|
@@ -3,9 +3,8 @@
|
|
3
3
|
# Generated by LapisLazuli, version <%= config[:lapis_lazuli][:version] %>
|
4
4
|
# Author: "<%= config[:user] %>" <<%= config[:email] %>>
|
5
5
|
#
|
6
|
-
#
|
7
|
-
# This
|
8
|
-
# Example > Cucumber -t @homepage -p default -p localhost
|
6
|
+
# Cucumber profiles are used to group certain tags and variables
|
7
|
+
# This way you can run specific scenario's on specific environments.
|
9
8
|
|
10
9
|
<%% timestamp = Time.now.strftime("%Y%m%d_%H%M") %>
|
11
10
|
|
@@ -17,19 +16,49 @@ html_report: -f pretty -f html --out=results/<%%=timestamp%>_report.html
|
|
17
16
|
junit_report: -f pretty -f junit --out=results
|
18
17
|
|
19
18
|
################################################################################
|
20
|
-
# Supported browsers (default =
|
19
|
+
# Supported browsers (default = chrome)
|
20
|
+
chrome: BROWSER=chrome
|
21
21
|
ff: BROWSER=firefox
|
22
22
|
firefox: BROWSER=firefox
|
23
|
-
chrome: BROWSER=chrome
|
24
|
-
ie: BROWSER=ie
|
25
|
-
safari: BROWSER=safari
|
26
|
-
edge: BROWSER=edge
|
27
|
-
|
28
23
|
|
29
24
|
################################################################################
|
30
25
|
# Listed environments (default is set in config.yml)
|
31
|
-
t:
|
32
|
-
test: TEST_ENV=test -t @t
|
26
|
+
t: -p test
|
27
|
+
test: TEST_ENV=test -t '@t or @test or @all_env or @all_environments' -t 'not @disabled_on_test'
|
28
|
+
# When you run cucumber -p t
|
29
|
+
# 1. t: -p test > will call profile `test`
|
30
|
+
# 2. TEST_ENV=test > Sets a ruby variable ENV['TEST_ENV'] = 'test'
|
31
|
+
# 3. '@t or @test or @all_env or @all_environments' > Runs all features / scenario's that include either one of these tags
|
32
|
+
# 4. -t 'not @disabled_on_test' > Will not run any feature / scenario that includes this that
|
33
|
+
# A scenario including '@test @disabled_on_test', will be ignored!
|
34
|
+
|
35
|
+
a: -p acceptance
|
36
|
+
acc: -p acceptance
|
37
|
+
accpetance: TEST_ENV=acceptance -t '@a or @acceptance or @all_env or @all_environments' -t 'not @disabled_on_acceptance' -t 'not @disabled_on_acc'
|
38
|
+
|
39
|
+
p: -p production
|
40
|
+
prod: -p production
|
41
|
+
production: TEST_ENV=production -t '@p or @prod or @production or @all_env or @all_environments' -t 'not @disabled_on_production' -t 'not @disabled_on_prod'
|
42
|
+
|
43
|
+
################################################################################
|
44
|
+
# The following is another exmaple of creating (and combining) profiles. In this one we use Version. But it could be anything really.
|
45
|
+
# With version profile you can easily combine a certain environment with a version
|
46
|
+
# An then include (or exclude) certain scenario's that are only available on a specific version.
|
47
|
+
# E.G.: bundle exec cucucumber -p acceptance -p version_14
|
48
|
+
|
49
|
+
v_12: -p version_12
|
50
|
+
version_12: VERSION=12 -t '@v_12 or @ver_12 or @version_12 or @all_versions' -t 'not @disabled_on_ver_12' -t 'not @disabled_on_version_12'
|
51
|
+
|
52
|
+
v_14: -p version_14
|
53
|
+
version_14: VERSION=14 -t '@v_14 or @ver_14 or @version_14 or @all_versions' -t 'not @disabled_on_ver_14' -t 'not @disabled_on_version_14'
|
33
54
|
|
34
|
-
|
35
|
-
|
55
|
+
################################################################################
|
56
|
+
# A few example cucumber commands you could execute:
|
57
|
+
# Run all acceptance tests
|
58
|
+
# bundle exec cucumber -p acc
|
59
|
+
#
|
60
|
+
# Only test a specific scenario on production
|
61
|
+
# bundle exec cucumber -p prod -t @login
|
62
|
+
#
|
63
|
+
# Use the default environment set in config.yml and run a specific tag with extended output
|
64
|
+
# bundle exec cucumber -t @test_24 -x
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
users:
|
3
|
+
default-user: # See ./features/helpers/user_helper.rb
|
4
|
+
username: ta_RAND-ALPHA_
|
5
|
+
password: Ab!2_RAND_
|
6
|
+
gender: male
|
7
|
+
experience: Ruby,Gherkin
|
8
|
+
biography: This is the default test user
|
9
|
+
complete_all: 1
|
10
|
+
production:
|
11
|
+
test-user:
|
12
|
+
username: test
|
13
|
+
password: test
|
14
|
+
test:
|
15
|
+
test-user:
|
16
|
+
username: ta-test-user
|
17
|
+
password: ^%8jah7hH
|
18
|
+
uat:
|
19
|
+
test-user:
|
20
|
+
username: ta-uat-user
|
21
|
+
password: (87hsjaJH#
|
@@ -0,0 +1,49 @@
|
|
1
|
+
@basic @all_env
|
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
|
+
@basic_01
|
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 somewhere on the page
|
12
|
+
|
13
|
+
@basic_02
|
14
|
+
Scenario: example02 - scrolling down
|
15
|
+
Given the user navigates to "home"
|
16
|
+
When the user scrolls down
|
17
|
+
Then text "Project-based services are typically short-term" should display somewhere on the page
|
18
|
+
|
19
|
+
@basic_03
|
20
|
+
Scenario: example03 - Going to a search result
|
21
|
+
Given the user navigates to "https://www.spritecloud.com/?s=lapis+lazuli"
|
22
|
+
When the user scrolls down
|
23
|
+
And the user clicks on link "/announcing-lapislazuli/"
|
24
|
+
Then text "A few days later you are working" should display somewhere on the page
|
25
|
+
|
26
|
+
@basic_04
|
27
|
+
Scenario Outline: example04 - checking multiple pages for the logo
|
28
|
+
Given the user navigates to "<page>"
|
29
|
+
When the user clicks on the spritecloud logo
|
30
|
+
Then the user should be on page "home"
|
31
|
+
Scenarios:
|
32
|
+
| page |
|
33
|
+
| blog |
|
34
|
+
| home |
|
35
|
+
| about-us |
|
36
|
+
| testing |
|
37
|
+
| functional-testing |
|
38
|
+
|
39
|
+
### LEARNING TO DEBUG ###
|
40
|
+
# Scenario' or Feature's including the tag @dev will be ingored when running a regular profile. To run this do:
|
41
|
+
# bundle exec cucumber -t @basic_04 -p debug
|
42
|
+
# or, if you want to test it on a specific environment:
|
43
|
+
# bundle exec cucumber -p production -p debug -t @basic_04
|
44
|
+
# Good luck fixing the problems!
|
45
|
+
@basic_05 @dev
|
46
|
+
Scenario: example_05 - confirming there is a no results page
|
47
|
+
Given the user navigates to "blog"
|
48
|
+
When the user searches for "no_results_expected"
|
49
|
+
Then the text "Nothing Found" should display on the blog page
|
@@ -0,0 +1,38 @@
|
|
1
|
+
@account @all_env
|
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
|
+
@account_01 @log_in #@pause # You can add @pause to have a break between every step.
|
11
|
+
Scenario: account_01 - Logging in
|
12
|
+
Given the user is logged out
|
13
|
+
When "test-user" logs in
|
14
|
+
Then the page should display as logged in state
|
15
|
+
|
16
|
+
@account_02 @log_out
|
17
|
+
Scenario: account_02 - Logging out
|
18
|
+
Given "test-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
|
+
@account_03
|
23
|
+
Scenario: account_03 - Opening the registration form
|
24
|
+
Given the user is logged out
|
25
|
+
When the user clicks on the registration button
|
26
|
+
Then the registration form should display
|
27
|
+
|
28
|
+
@account_04
|
29
|
+
Scenario: account_04 - Successful registration
|
30
|
+
Given "default-user" has the registration form opened
|
31
|
+
When the user completes registration
|
32
|
+
Then the successful registration message should display
|
33
|
+
|
34
|
+
@account_05
|
35
|
+
Scenario: account_05 - Logging in a new registration
|
36
|
+
Given "default-user" has registered a new account
|
37
|
+
When the user logs in
|
38
|
+
Then the page should display as logged in state
|
@@ -0,0 +1,23 @@
|
|
1
|
+
@todo @all_env
|
2
|
+
Feature: Todo list
|
3
|
+
In this feature we will test the todo functionality
|
4
|
+
We do this by adding, completing and deleting the todo lists'
|
5
|
+
|
6
|
+
@todo_01
|
7
|
+
Scenario: todo_01 - adding a todo item
|
8
|
+
Given "test-user" is logged in
|
9
|
+
When a todo item with text "Hello world" is added
|
10
|
+
Then a todo item with text "Hello world" should be present
|
11
|
+
|
12
|
+
@todo_02
|
13
|
+
Scenario: todo_02 - removing all todo items
|
14
|
+
Given "test-user" has at least 1 todo item
|
15
|
+
When the user marks all todo items as completed
|
16
|
+
And the clear completed button is pressed
|
17
|
+
Then no todo items should display
|
18
|
+
|
19
|
+
@todo_03
|
20
|
+
Scenario: todo_03 - confirming the progress bar
|
21
|
+
Given "test-user" has exactly 8 todo items
|
22
|
+
When the user marks 4 todo items as completed
|
23
|
+
Then the progress bar should display at 50 percent
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Auth
|
2
|
+
# This is the Authentication helper, it will have all functions to log in, log out or ensure one of these statusses.
|
3
|
+
# For every part of functionality of a project, you can create a new helper, to keep your TA organised.
|
4
|
+
extend LapisLazuli
|
5
|
+
class << self
|
6
|
+
|
7
|
+
@@user = ''
|
8
|
+
@login_page = 'training-page'
|
9
|
+
|
10
|
+
# This is a list of elements relevant for this helper.
|
11
|
+
# The following is short notation, *only* use this if the element selector can be done in 1 line.
|
12
|
+
# @formatter:off
|
13
|
+
def form_container; browser.wait(:like => [:form, :id, 'form-login']); end
|
14
|
+
def username_field; form_container.input(:xpath => '//*[@id="login-username"]'); end
|
15
|
+
def password_field; form_container.input(:id => 'login-password'); end
|
16
|
+
def login_button; browser.button(:id => 'button-login'); end
|
17
|
+
# @formatter:on
|
18
|
+
|
19
|
+
# Following elements that need more advanced options/search patterns
|
20
|
+
def logged_in_element(timeout=10, throw=true)
|
21
|
+
browser.wait(
|
22
|
+
:like => [:a, :id, 'user_dropdown'],
|
23
|
+
:timeout => timeout,
|
24
|
+
:throw => throw
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def logged_out_element(timeout=10, throw=true)
|
29
|
+
browser.wait(
|
30
|
+
:like => [:form, :id, 'form-login'],
|
31
|
+
:timeout => timeout,
|
32
|
+
:throw => throw
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Next are the functions called from the step definitions
|
37
|
+
# `ensure_something` is best practise to be used for functions that should get the test to a certain state. For example:
|
38
|
+
# `ensure_log_out` only logs out if you're logged in
|
39
|
+
# `log_out` will blindly try to log out and fail if you're already logged out
|
40
|
+
def ensure_log_out
|
41
|
+
Nav.to('training-page')
|
42
|
+
if Auth.is_logged_in?
|
43
|
+
Auth.log_out
|
44
|
+
if Auth.is_logged_in?
|
45
|
+
error 'Page did not display in logged out state after logging out'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Makes sure that a specific user is logged in, if it's not already.
|
51
|
+
def ensure_log_in(user='default-user')
|
52
|
+
Nav.to('training-page')
|
53
|
+
unless Auth.is_logged_in?(user)
|
54
|
+
# If the wrong user is logged in, we should ensure a log out action and then log in again
|
55
|
+
Auth.ensure_log_out
|
56
|
+
Auth.log_in(user)
|
57
|
+
# Double check if the login was successful, if not, throw an error.
|
58
|
+
unless Auth.is_logged_in?(user)
|
59
|
+
error "Failed to log in `#{user}`."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# If user=nil, any logged in user is acceptable, else we want to make sure the username matches with the logged in user.
|
65
|
+
def is_logged_in?(user=nil)
|
66
|
+
# For performance, we do a 0 second wait for the logged_out_element
|
67
|
+
if Auth.logged_out_element(0, false)
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
login_elm = Auth.logged_in_element(5, false)
|
71
|
+
if login_elm.nil?
|
72
|
+
# Logged in element not found, check if the logged out element is present
|
73
|
+
logout_elm = Auth.logged_out_element(0, false)
|
74
|
+
if logout_elm.nil?
|
75
|
+
# Neither of the elements were present, this should not be possible.
|
76
|
+
error 'Failed to find the logged_out element and the logged_in element. The user is not logged in, nor logged out.'
|
77
|
+
else
|
78
|
+
# Logged out element was found the second time.
|
79
|
+
return false
|
80
|
+
end
|
81
|
+
else
|
82
|
+
# The logged in element was found, should we match the username?
|
83
|
+
if user.nil?
|
84
|
+
# No, any user is fine
|
85
|
+
return true
|
86
|
+
else
|
87
|
+
# Yes, load the user data and match the username
|
88
|
+
User.load_user_data(user)
|
89
|
+
return login_elm.span(:class => ['username', 'ng-binding']).text == User.get('username')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def log_out
|
95
|
+
Auth.logged_in_element.click
|
96
|
+
dropdown = browser.wait(:like => [:ul, :class, 'dropdown-menu'])
|
97
|
+
browser.find(
|
98
|
+
:like => [:a, :id, 'link-logout'],
|
99
|
+
:context => dropdown
|
100
|
+
).click
|
101
|
+
end
|
102
|
+
|
103
|
+
def log_in(user=nil, renew_session=false)
|
104
|
+
# If user=nil, we expect that there already is user data loaded in a previous step.
|
105
|
+
User.load_user_data(user) unless user.nil?
|
106
|
+
|
107
|
+
Auth.username_field.to_subtype.to_subtype.set(User.get('username'))
|
108
|
+
Auth.password_field.to_subtype.to_subtype.set(User.get('password'))
|
109
|
+
Auth.login_button.click
|
110
|
+
|
111
|
+
unless Auth.is_logged_in? user
|
112
|
+
alert = browser.find(:like => [:div, :class, 'alert'], :throw => false)
|
113
|
+
if alert.nil?
|
114
|
+
error "Failed to log in user #{user}"
|
115
|
+
else
|
116
|
+
alert.flash
|
117
|
+
error "Found error while logging in #{user}: `#{alert.html}`"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Simple helper that makes navigating using the config file easier
|
2
|
+
# It will check if a given string is a URL or a config value and goto that page accordingly
|
3
|
+
module Nav
|
4
|
+
extend LapisLazuli
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Navigates to a given URL or page.url configuration if the current URL is not the same
|
8
|
+
# Then confirms that the new URL is loaded.
|
9
|
+
def to(config_page_or_url, force_refresh = false)
|
10
|
+
url = self.set_url(config_page_or_url)
|
11
|
+
browser.goto url unless url == browser.url and !force_refresh
|
12
|
+
Nav.wait_for_url url
|
13
|
+
end
|
14
|
+
|
15
|
+
# Waits until the browser URL is the same as the given URL
|
16
|
+
def wait_for_url(url)
|
17
|
+
browser.wait_until(timeout: 5, message: "URL did not become `#{url}`") {
|
18
|
+
browser.url.include? url
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Loads the URL from the config, prioritized from top to bottom:
|
23
|
+
# production.pages.home
|
24
|
+
# production.pages.home.path
|
25
|
+
# pages.home
|
26
|
+
# pages.home.path
|
27
|
+
def get_url page
|
28
|
+
begin
|
29
|
+
return env_or_config("pages.#{page}")
|
30
|
+
rescue RuntimeError
|
31
|
+
return env_or_config("pages.#{page}.path")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Confirms if the given URL is a valid URL
|
36
|
+
def is_url? string
|
37
|
+
uri = URI.parse(string)
|
38
|
+
%w( http https ).include?(uri.scheme)
|
39
|
+
rescue URI::BadURIError
|
40
|
+
false
|
41
|
+
rescue URI::InvalidURIError
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# returns the expected URL
|
46
|
+
def set_url(config_page_or_url)
|
47
|
+
if Nav.is_url? config_page_or_url
|
48
|
+
# Return the given URL if it alreadt is a valid URL
|
49
|
+
return config_page_or_url
|
50
|
+
else
|
51
|
+
# Look for the URL in the config files
|
52
|
+
path_or_url = get_url config_page_or_url
|
53
|
+
if Nav.is_url? path_or_url
|
54
|
+
# If it is a URL now, then return it
|
55
|
+
return path_or_url
|
56
|
+
else
|
57
|
+
# Else add an expected 'root' to the path.
|
58
|
+
return env('root') + path_or_url
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Register
|
2
|
+
|
3
|
+
extend LapisLazuli
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# This is a list of elements relevant for this helper.
|
7
|
+
# The following is short notation, *only* use this if the element selector can be done in 1 line.
|
8
|
+
# @formatter:off
|
9
|
+
def form; browser.wait(:like => [:form, :id, 'form-register']); end
|
10
|
+
def open_register_button; browser.find(:like => [:button, :id, 'button-register']); end
|
11
|
+
def username_field; browser.wait(:element => {:name => 'username'}, :context => Register.form); end
|
12
|
+
def password_field; browser.find(:element => {:name => 'password'}, :context => Register.form); end
|
13
|
+
def experience_field; browser.find(:like => [:select, :id, "register-experience"], :context => form); end
|
14
|
+
def biography_field; browser.find(:like => [:textarea, :id, 'register-bio']); end
|
15
|
+
def policy_checkbox; browser.find(:like => [:input, :id, 'register-complete-all']) end
|
16
|
+
def submit_button; browser.find(:button => {:id => 'button-save'}, :context => Register.form); end
|
17
|
+
# @formatter:on
|
18
|
+
|
19
|
+
def gender_radio(gender)
|
20
|
+
browser.find(
|
21
|
+
:label => {:text => /#{gender}/i},
|
22
|
+
:context => Register.form,
|
23
|
+
:message => "Unable to find gender `#{gender}`, are you sure it's an option to select?"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def select_experiences(*experience_list)
|
28
|
+
experience_list.each do |exp|
|
29
|
+
option = browser.find(
|
30
|
+
:option => {:value => /#{exp}/i},
|
31
|
+
:context => Register.experience_field
|
32
|
+
)
|
33
|
+
option.click(:control)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# The following 3 functions are a typical example of something to use.
|
38
|
+
# First a function in which you perform an action (open_something, click_something, press_something)
|
39
|
+
def open_registration
|
40
|
+
Register.open_register_button.click
|
41
|
+
end
|
42
|
+
|
43
|
+
# Second, a function that confirms that the action was successful
|
44
|
+
def is_registration_open?
|
45
|
+
return Register.form rescue false
|
46
|
+
end
|
47
|
+
|
48
|
+
# And finally as function that ensures an action was successfully completed.
|
49
|
+
def ensure_open_registrarion
|
50
|
+
Auth.ensure_log_out
|
51
|
+
Register.open_registration unless Register.is_registration_open?
|
52
|
+
end
|
53
|
+
|
54
|
+
def fill_form
|
55
|
+
#the setter goes too fast sometimes not finishing the username, this will re-set the username when it does
|
56
|
+
browser.wait_until(timeout: 10, message: 'False did not become true withing 10 seconds') {
|
57
|
+
Register.username_field.to_subtype.set(User.get('username'))
|
58
|
+
Register.username_field.value == User.get('username')
|
59
|
+
}
|
60
|
+
Register.username_field.to_subtype.set(User.get('username'))
|
61
|
+
Register.password_field.to_subtype.set(User.get('password'))
|
62
|
+
Register.gender_radio(User.get('gender')).click
|
63
|
+
Register.select_experiences(User.get('experience').split(','))
|
64
|
+
Register.biography_field.to_subtype.set(User.get('biography'))
|
65
|
+
Register.policy_checkbox.to_subtype.set((User.get('complete_all').to_i == 1))
|
66
|
+
end
|
67
|
+
|
68
|
+
def submit_form
|
69
|
+
Register.submit_button.click
|
70
|
+
browser.wait(
|
71
|
+
:like => [:div, :class, 'modal-backdrop fade in'],
|
72
|
+
:condition => :while
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def register_user
|
77
|
+
Register.fill_form
|
78
|
+
Register.submit_form
|
79
|
+
end
|
80
|
+
|
81
|
+
def registration_result
|
82
|
+
alert = browser.wait(like: [:div, :class, 'alert'], timeout: 2, throw: false)
|
83
|
+
if alert.nil?
|
84
|
+
return false, 'No message was displayed after registering'
|
85
|
+
elsif !alert.html.include? User.get('username')
|
86
|
+
return false, "An error message did display, but didn't contain the expected text: `#{alert.html}`"
|
87
|
+
end
|
88
|
+
return true, 'Successfully found the success message'
|
89
|
+
end
|
90
|
+
|
91
|
+
def ensure_registered(user)
|
92
|
+
begin
|
93
|
+
Auth.ensure_log_in(user)
|
94
|
+
Auth.log_out
|
95
|
+
rescue Exception => e
|
96
|
+
Register.ensure_open_registrarion
|
97
|
+
Register.register_user
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|