qable 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE +20 -0
- data/README.md +38 -0
- data/Rakefile +10 -0
- data/bin/console +13 -0
- data/bin/qable +5 -0
- data/bin/setup +8 -0
- data/exe/qable +5 -0
- data/lib/qable.rb +4 -0
- data/lib/qable/generators/app/app_generator.rb +69 -0
- data/lib/qable/generators/app/templates/Gemfile +7 -0
- data/lib/qable/generators/app/templates/README.md +146 -0
- data/lib/qable/generators/app/templates/Rakefile +13 -0
- data/lib/qable/generators/app/templates/config.yml +24 -0
- data/lib/qable/generators/app/templates/features/google_search.feature +11 -0
- data/lib/qable/generators/app/templates/features/step_definitions/custom_steps.rb +1 -0
- data/lib/qable/generators/app/templates/features/support/custom_matchers.rb +1 -0
- data/lib/qable/generators/app/templates/features/support/env.rb +1 -0
- data/lib/qable/generators/app/templates/features/support/hooks.rb +34 -0
- data/lib/qable/generators/app/templates/gitignore +1 -0
- data/lib/qable/step_definitions/web_steps.rb +188 -0
- data/lib/qable/support.rb +5 -0
- data/lib/qable/support/env.rb +72 -0
- data/lib/qable/support/html_selectors_helpers.rb +43 -0
- data/lib/qable/support/navigation_helpers.rb +35 -0
- data/lib/qable/support/page_objects.rb +37 -0
- data/lib/qable/version.rb +3 -0
- data/qable.gemspec +29 -0
- data/selenium-ie11-key.reg +3 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: eded589eb9691f96ed51e3e27b450f2c656b5a3a
|
4
|
+
data.tar.gz: 99dba7dba7fec60e2f905a8793f53c8213ea23e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3eea44f19e2264f65c576234ca0e4c298288e9ce3b3230ca0a3fc1d847bfc63cc9ce085a4aa3aaa3b334fed04c2cc028f03d0c409cc13372920e87276ddc9caa
|
7
|
+
data.tar.gz: 9fd8b648ff769f979a0f1d5a989f064b30d4c59451cb44b4815bbc31edb7ed4e0b7c74d6bddf0d7e5329d39f89102eb529857ce57a9110d992975753aef1b992
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2017 Able.co
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Qable
|
2
|
+
|
3
|
+
Qable is a acceptance testing framework based in Cucumber/Capybara with
|
4
|
+
Page Object Model DSL and multi-browser support.
|
5
|
+
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install it yourself as:
|
10
|
+
|
11
|
+
$ gem install qable
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
Create a new project:
|
16
|
+
|
17
|
+
$ qable myapp
|
18
|
+
|
19
|
+
Run the tests in the new project:
|
20
|
+
|
21
|
+
$ cd myapp
|
22
|
+
$ bundle exec rake
|
23
|
+
|
24
|
+
Read more about how to use Qable in the [project's README](https://github.com/ableco/qable/blob/master/lib/qable/generators/app/templates/README.md).
|
25
|
+
|
26
|
+
## Development
|
27
|
+
|
28
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
29
|
+
|
30
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
31
|
+
|
32
|
+
## Contributing
|
33
|
+
|
34
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ableco/qable.
|
35
|
+
|
36
|
+
## Copyright
|
37
|
+
|
38
|
+
Copyright (c) 2017 Able.co. See LICENSE for further details.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
|
5
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
6
|
+
# with your gem easier. You can also use a different console, if you like.
|
7
|
+
|
8
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
9
|
+
# require "pry"
|
10
|
+
# Pry.start
|
11
|
+
|
12
|
+
require "irb"
|
13
|
+
IRB.start(__FILE__)
|
data/bin/qable
ADDED
data/bin/setup
ADDED
data/exe/qable
ADDED
data/lib/qable.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Qable
|
2
|
+
module Generators
|
3
|
+
module App
|
4
|
+
class AppGenerator < Thor::Group
|
5
|
+
include Thor::Actions
|
6
|
+
|
7
|
+
argument :name
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
File.dirname(__FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_base_dir
|
14
|
+
self.destination_root = File.expand_path(name, destination_root)
|
15
|
+
empty_directory '.'
|
16
|
+
inside destination_root do
|
17
|
+
create_readme
|
18
|
+
create_gemfile
|
19
|
+
create_rakefile
|
20
|
+
create_config
|
21
|
+
create_gitignore
|
22
|
+
create_features_directory
|
23
|
+
create_page_objects_directory
|
24
|
+
create_reports_directory
|
25
|
+
run_bundle
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def create_readme
|
32
|
+
template('templates/README.md', 'README.md')
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_gemfile
|
36
|
+
template('templates/Gemfile', 'Gemfile')
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_rakefile
|
40
|
+
template('templates/Rakefile', 'Rakefile')
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_config
|
44
|
+
template('templates/config.yml', 'config.yml')
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_gitignore
|
48
|
+
template('templates/gitignore', '.gitignore')
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_features_directory
|
52
|
+
directory('templates/features', 'features')
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_page_objects_directory
|
56
|
+
empty_directory 'page_objects'
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_reports_directory
|
60
|
+
empty_directory 'reports'
|
61
|
+
end
|
62
|
+
|
63
|
+
def run_bundle
|
64
|
+
run 'bundle install'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# <%= name.capitalize %>
|
2
|
+
|
3
|
+
## Getting Started
|
4
|
+
|
5
|
+
Install QAble and their dependencies if you haven't yet:
|
6
|
+
|
7
|
+
```
|
8
|
+
bundle install
|
9
|
+
```
|
10
|
+
|
11
|
+
With the dependencies installed you can proceed to run tests.
|
12
|
+
|
13
|
+
## Configuration
|
14
|
+
|
15
|
+
The project is configured through the `config.yml` file in the root directory.
|
16
|
+
see this file for all the values that can be configured and examples about how
|
17
|
+
to set them.
|
18
|
+
|
19
|
+
## Browsers Support
|
20
|
+
|
21
|
+
QAble supports Chrome and Firefox by default in all the OS supported by Selenium (OS X, Linux, Windows, ...)
|
22
|
+
without installing any extra dependencies if the browsers are installed (e.g you need to install Firefox to run tests in Firefox).
|
23
|
+
|
24
|
+
Tests can be executed in Internet Explorer and Edge if a Windows Machine with Selenium
|
25
|
+
Server is set and configured. (instructions about setting a server are below in the `Windows Browsers support through Selenium Server` section)
|
26
|
+
|
27
|
+
Safari support under OS X is under work.
|
28
|
+
|
29
|
+
Internet Explorer and Edge under Windows will be supported soon.
|
30
|
+
|
31
|
+
## Running tests
|
32
|
+
|
33
|
+
```
|
34
|
+
bundle exec rake
|
35
|
+
```
|
36
|
+
|
37
|
+
By default tests are run in all supported browsers to change that edit
|
38
|
+
the `config.yml` in project directory.
|
39
|
+
|
40
|
+
The results of the tests are displayed in console and saved to `reports`
|
41
|
+
folder on the project.
|
42
|
+
|
43
|
+
## Available Steps
|
44
|
+
|
45
|
+
By default Qable include a set of tests useful for testing the behavior
|
46
|
+
of web sites. See the [Web Steps file](https://github.com/ableco/qable/blob/master/lib/qable/step_definitions/web_steps.rb)
|
47
|
+
to learn about the available stepts.
|
48
|
+
|
49
|
+
## Referencing Paths
|
50
|
+
|
51
|
+
Paths can be referenced by url or name in features files.
|
52
|
+
|
53
|
+
To specify paths by url just puth the url that you want to visit, e.g:
|
54
|
+
|
55
|
+
```
|
56
|
+
Given I go to /sign_in
|
57
|
+
```
|
58
|
+
|
59
|
+
To specify paths by name add the alias in paths section in the `config.yml`:
|
60
|
+
|
61
|
+
```
|
62
|
+
paths
|
63
|
+
login: /sign_in
|
64
|
+
```
|
65
|
+
|
66
|
+
and reference it in the feature file:
|
67
|
+
|
68
|
+
```
|
69
|
+
Given I go to login page
|
70
|
+
```
|
71
|
+
|
72
|
+
## Adding custom step definitions
|
73
|
+
|
74
|
+
Custom step definitions can be added in the `features/step_definitions` folder
|
75
|
+
in the project. By default `custom_steps.rb` file lives in this folder
|
76
|
+
and can be edited to add the new steps.
|
77
|
+
|
78
|
+
## Visualizing Failing tests
|
79
|
+
|
80
|
+
The screenshots for failing tests are saved by default in `reports`
|
81
|
+
folder and displayed in the corresponding report file along with the failing
|
82
|
+
step.
|
83
|
+
|
84
|
+
## Page Object Support
|
85
|
+
|
86
|
+
Page Object Model DSL is supported if the `site_prism` gem is added to the
|
87
|
+
project's Gemfile.
|
88
|
+
|
89
|
+
To use Page Object Model just add the Ruby files describing the site to
|
90
|
+
the `page_objects` folder in the project.
|
91
|
+
|
92
|
+
Check [SitePrism](https://github.com/natritmeyer/site_prism#siteprism)
|
93
|
+
for more details about using Page Object Model DSL.
|
94
|
+
|
95
|
+
## Windows Browsers support through Selenium Server
|
96
|
+
|
97
|
+
QAble can be used with Selenium Server to run tests in Windows for browsers not
|
98
|
+
supported by OS X.
|
99
|
+
|
100
|
+
The next steps can be executed in a Windows machine to configure Selenium Server
|
101
|
+
along with IE driver and Edge's Web Driver for Selenium:
|
102
|
+
|
103
|
+
First download `selenium-server-standalone` and `IEDriverServer` from
|
104
|
+
[Selenium website](http://selenium-release.storage.googleapis.com/index.html?path=3.6/)
|
105
|
+
|
106
|
+
For Edge download [Microsoft WebDriver](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/)
|
107
|
+
|
108
|
+
|
109
|
+
Start a Selenium Hub:
|
110
|
+
|
111
|
+
```
|
112
|
+
java -jar selenium-server-standalone-3.6.0.jar -role hub
|
113
|
+
```
|
114
|
+
|
115
|
+
Register IE Node (change the location of IEDriverServer.exe according to
|
116
|
+
your system)
|
117
|
+
|
118
|
+
```
|
119
|
+
java -Dwebdriver.ie.driver=C:\Users\User\Selenium\IEDriverServer.exe -jar selenium-server-standalone-3.6.0.jar -role node -hub http://10.0.2.15:4444/grid/register -browser "browserName=internet explorer,platform=WINDOWS,maxInstances=10"
|
120
|
+
```
|
121
|
+
|
122
|
+
Register Edge Node (change the location of MicrosoftWebDriver.exe according to
|
123
|
+
your system)
|
124
|
+
|
125
|
+
```
|
126
|
+
java -Dwebdriver.edge.driver=C:\Users\User\Selenium\MicrosoftWebDriver.exe -jar selenium-server-standalone-3.6.0.jar -role node -hub http://10.0.2.15:4444/grid/register -browser "browserName=MicrosoftEdge,platform=WINDOWS,maxInstances=10"
|
127
|
+
```
|
128
|
+
|
129
|
+
Edit the `remote_ci_url` in your project `config.yml` and set it to the
|
130
|
+
Selenium Hub URL, e.g:
|
131
|
+
|
132
|
+
```
|
133
|
+
remote_ci_url: http://192.168.56.2:4444/wd/hub
|
134
|
+
```
|
135
|
+
|
136
|
+
|
137
|
+
### Internet Explorer caveats
|
138
|
+
|
139
|
+
- If you’re running a 64-bit version of Windows, do not go with the 64-bit IE
|
140
|
+
driver for IE 10+. This is the source of incredibly slow typing.
|
141
|
+
|
142
|
+
- IE 11 requires a registry key to be set, otherwise connections to the browser
|
143
|
+
process will drop out. [Here’s a registry export snippet]() for 64-bit Windows.
|
144
|
+
|
145
|
+
- Some systems require moving the Security level from `High` to `Medium`
|
146
|
+
in Internet Options -> Security to work correctly.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.require
|
4
|
+
|
5
|
+
task :default => :cucumber
|
6
|
+
task :cucumber do
|
7
|
+
Dir.mkdir("reports") unless Dir.exist?("reports")
|
8
|
+
browsers = YAML.load_file(File.join(Dir.pwd, "config.yml"))["browsers"]
|
9
|
+
time = Time.now.iso8601
|
10
|
+
browsers.each do |browser|
|
11
|
+
sh "BROWSER=#{browser} cucumber -r features features/*.feature -f pretty -f html -o reports/report-#{browser}-#{time}.html"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# The url of the site to run tests.
|
2
|
+
site: https://google.com
|
3
|
+
|
4
|
+
# List of browsers to run tests, note that Edge and IE requires setting a value for `remote_ci_url` below.
|
5
|
+
browsers:
|
6
|
+
- chrome
|
7
|
+
- firefox
|
8
|
+
# - edge
|
9
|
+
# - ie
|
10
|
+
# - safari
|
11
|
+
|
12
|
+
# Using custom Capybara drivers:
|
13
|
+
# `selenium`: requires geckodriver https://github.com/DevicoSolutions/geckodriver-helper
|
14
|
+
# `selenium_chrome`, `selenium_chrome_headless`: requires chromedriver https://github.com/flavorjones/chromedriver-helper
|
15
|
+
# `webkit`: requires capybara-webkit https://github.com/thoughtbot/capybara-webkit
|
16
|
+
# driver: selenium_chrome_headless
|
17
|
+
|
18
|
+
# Set this to be able to use Edge and IE with a remote server, this should be the full Selenium Hub URL, e.g: http://<CI-HOST>:4444/wd/hub
|
19
|
+
remote_ci_url:
|
20
|
+
|
21
|
+
# Add custom path names to use in steps, e.g: "Given I go to login page"
|
22
|
+
paths:
|
23
|
+
home: /
|
24
|
+
# login: /sign_up
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Feature: Search
|
2
|
+
As a user
|
3
|
+
I want to search web pages
|
4
|
+
So I can find relevant information
|
5
|
+
|
6
|
+
@javascript
|
7
|
+
Scenario: User search "Able.co"
|
8
|
+
Given I go to the homepage
|
9
|
+
And I fill in "q" with "Able.co"
|
10
|
+
When I press "Buscar con Google"
|
11
|
+
Then I should see "Able owns, operates, and invests in a portfolio of technology companies"
|
@@ -0,0 +1 @@
|
|
1
|
+
# Add your custom step definitions in this file
|
@@ -0,0 +1 @@
|
|
1
|
+
# Add rspec-matchers gem to your Gemfile and add your custom matchers in this file
|
@@ -0,0 +1 @@
|
|
1
|
+
require "qable/support"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Cucumber provides a number of hooks which allow us to run blocks at various points in the Cucumber test cycle
|
2
|
+
|
3
|
+
Before do
|
4
|
+
# Do something before each scenario.
|
5
|
+
end
|
6
|
+
|
7
|
+
Before do |scenario|
|
8
|
+
# The +scenario+ argument is optional, but if you use it, you can get the title,
|
9
|
+
# description, or name (title + description) of the scenario that is about to be
|
10
|
+
# executed.
|
11
|
+
end
|
12
|
+
|
13
|
+
After do
|
14
|
+
# Do something after each scenario.
|
15
|
+
end
|
16
|
+
|
17
|
+
After do |scenario|
|
18
|
+
# Do something after each scenario.
|
19
|
+
# The +scenario+ argument is optional, but
|
20
|
+
# if you use it, you can inspect status with
|
21
|
+
# the #failed?, #passed? and #exception methods.
|
22
|
+
end
|
23
|
+
|
24
|
+
#Tagged hooks
|
25
|
+
|
26
|
+
Before('@Ex_tag1 or @Ex_tag2') do
|
27
|
+
# This will only run before scenarios tagged
|
28
|
+
# with @cucumis OR @sativus.
|
29
|
+
end
|
30
|
+
|
31
|
+
AfterStep('@Ex_tag1 and @Ex_tag2') do
|
32
|
+
# This will only run after steps within scenarios tagged
|
33
|
+
# with @cucumis AND @sativus.
|
34
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
reports
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "cgi"
|
3
|
+
require "cucumber"
|
4
|
+
|
5
|
+
module WithinHelpers
|
6
|
+
def with_scope(locator)
|
7
|
+
locator ? within(*selector_for(locator)) { yield } : yield
|
8
|
+
end
|
9
|
+
end
|
10
|
+
World(WithinHelpers)
|
11
|
+
# Single-line step scoper
|
12
|
+
When /^(.*) within (.*[^:])$/ do |step, parent|
|
13
|
+
with_scope(parent) { When step }
|
14
|
+
end
|
15
|
+
# Multi-line step scoper
|
16
|
+
When /^(.*) within (.*[^:]):$/ do |step, parent, table_or_string|
|
17
|
+
with_scope(parent) { When "\#{step}:", table_or_string }
|
18
|
+
end
|
19
|
+
Given /^(?:|I )am on (.+)$/ do |page_name|
|
20
|
+
visit path_to(page_name)
|
21
|
+
end
|
22
|
+
When /^(?:|I )go to (.+)$/ do |page_name|
|
23
|
+
visit path_to(page_name)
|
24
|
+
end
|
25
|
+
When /^(?:|I )press "([^"]*)"$/ do |button|
|
26
|
+
click_button(button)
|
27
|
+
end
|
28
|
+
When /^(?:|I )follow "([^"]*)"$/ do |link|
|
29
|
+
click_link(link)
|
30
|
+
end
|
31
|
+
When /^(?:|I )fill in "([^"]*)" with "([^"]*)"$/ do |field, value|
|
32
|
+
fill_in(field, :with => value)
|
33
|
+
end
|
34
|
+
When /^(?:|I )fill in "([^"]*)" for "([^"]*)"$/ do |value, field|
|
35
|
+
fill_in(field, :with => value)
|
36
|
+
end
|
37
|
+
# Use this to fill in an entire form with data from a table. Example:
|
38
|
+
#
|
39
|
+
# When I fill in the following:
|
40
|
+
# | Account Number | 5002 |
|
41
|
+
# | Expiry date | 2009-11-01 |
|
42
|
+
# | Note | Nice guy |
|
43
|
+
# | Wants Email? | |
|
44
|
+
#
|
45
|
+
# TODO: Add support for checkbox, select or option
|
46
|
+
# based on naming conventions.
|
47
|
+
#
|
48
|
+
When /^(?:|I )fill in the following:$/ do |fields|
|
49
|
+
fields.rows_hash.each do |name, value|
|
50
|
+
When %{I fill in "\#{name}" with "\#{value}"}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
When /^(?:|I )select "([^"]*)" from "([^"]*)"$/ do |value, field|
|
54
|
+
select(value, :from => field)
|
55
|
+
end
|
56
|
+
When /^(?:|I )check "([^"]*)"$/ do |field|
|
57
|
+
check(field)
|
58
|
+
end
|
59
|
+
When /^(?:|I )uncheck "([^"]*)"$/ do |field|
|
60
|
+
uncheck(field)
|
61
|
+
end
|
62
|
+
When /^(?:|I )choose "([^"]*)"$/ do |field|
|
63
|
+
choose(field)
|
64
|
+
end
|
65
|
+
When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"$/ do |path, field|
|
66
|
+
attach_file(field, File.expand_path(path))
|
67
|
+
end
|
68
|
+
Then /^(?:|I )should see "([^"]*)"$/ do |text|
|
69
|
+
if page.respond_to? :should
|
70
|
+
page.should have_content(text)
|
71
|
+
else
|
72
|
+
assert page.has_content?(text)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
Then /^(?:|I )should not see "([^"]*)"$/ do |text|
|
76
|
+
if page.respond_to? :should
|
77
|
+
page.should have_no_content(text)
|
78
|
+
else
|
79
|
+
assert page.has_no_content?(text)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
Then /^the "([^"]*)" field(?: within (.*))? should contain "([^"]*)"$/ do |field, parent, value|
|
83
|
+
with_scope(parent) do
|
84
|
+
field = find_field(field)
|
85
|
+
field_value = (field.tag_name == 'textarea') ? field.text : field.value
|
86
|
+
if field_value.respond_to? :should
|
87
|
+
field_value.should =~ /\#{value}/
|
88
|
+
else
|
89
|
+
assert_match(/\#{value}/, field_value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
Then /^the "([^"]*)" field(?: within (.*))? should not contain "([^"]*)"$/ do |field, parent, value|
|
94
|
+
with_scope(parent) do
|
95
|
+
field = find_field(field)
|
96
|
+
field_value = (field.tag_name == 'textarea') ? field.text : field.value
|
97
|
+
if field_value.respond_to? :should_not
|
98
|
+
field_value.should_not =~ /\#{value}/
|
99
|
+
else
|
100
|
+
assert_no_match(/\#{value}/, field_value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
Then /^the "([^"]*)" field should have the error "([^"]*)"$/ do |field, error_message|
|
105
|
+
element = find_field(field)
|
106
|
+
classes = element.find(:xpath, '..')[:class].split(' ')
|
107
|
+
form_for_input = element.find(:xpath, 'ancestor::form[1]')
|
108
|
+
using_formtastic = form_for_input[:class].include?('formtastic')
|
109
|
+
error_class = using_formtastic ? 'error' : 'field_with_errors'
|
110
|
+
if classes.respond_to? :should
|
111
|
+
classes.should include(error_class)
|
112
|
+
else
|
113
|
+
assert classes.include?(error_class)
|
114
|
+
end
|
115
|
+
if page.respond_to?(:should)
|
116
|
+
if using_formtastic
|
117
|
+
error_paragraph = element.find(:xpath, '../*[@class="inline-errors"][1]')
|
118
|
+
error_paragraph.should have_content(error_message)
|
119
|
+
else
|
120
|
+
page.should have_content("\#{field.titlecase} \#{error_message}")
|
121
|
+
end
|
122
|
+
else
|
123
|
+
if using_formtastic
|
124
|
+
error_paragraph = element.find(:xpath, '../*[@class="inline-errors"][1]')
|
125
|
+
assert error_paragraph.has_content?(error_message)
|
126
|
+
else
|
127
|
+
assert page.has_content?("\#{field.titlecase} \#{error_message}")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
Then /^the "([^"]*)" field should have no error$/ do |field|
|
132
|
+
element = find_field(field)
|
133
|
+
classes = element.find(:xpath, '..')[:class].split(' ')
|
134
|
+
if classes.respond_to? :should
|
135
|
+
classes.should_not include('field_with_errors')
|
136
|
+
classes.should_not include('error')
|
137
|
+
else
|
138
|
+
assert !classes.include?('field_with_errors')
|
139
|
+
assert !classes.include?('error')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
Then /^the "([^"]*)" checkbox(?: within (.*))? should be checked$/ do |label, parent|
|
143
|
+
with_scope(parent) do
|
144
|
+
field_checked = find_field(label)['checked']
|
145
|
+
if field_checked.respond_to? :should
|
146
|
+
field_checked.should be_true
|
147
|
+
else
|
148
|
+
assert field_checked
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
Then /^the "([^"]*)" checkbox(?: within (.*))? should not be checked$/ do |label, parent|
|
153
|
+
with_scope(parent) do
|
154
|
+
field_checked = find_field(label)['checked']
|
155
|
+
if field_checked.respond_to? :should
|
156
|
+
field_checked.should be_false
|
157
|
+
else
|
158
|
+
assert !field_checked
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
Then /^(?:|I )should be on (.+)$/ do |page_name|
|
163
|
+
page_name.gsub!(/("|')/,"")
|
164
|
+
if page_name.start_with?("http")
|
165
|
+
current_path = current_url
|
166
|
+
else
|
167
|
+
current_path = URI.parse(current_url).path
|
168
|
+
end
|
169
|
+
if current_path.respond_to? :should
|
170
|
+
current_path.should == path_to(page_name)
|
171
|
+
else
|
172
|
+
assert_equal path_to(page_name), current_path
|
173
|
+
end
|
174
|
+
end
|
175
|
+
Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
|
176
|
+
query = URI.parse(current_url).query
|
177
|
+
actual_params = query ? CGI.parse(query) : {}
|
178
|
+
expected_params = {}
|
179
|
+
expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
|
180
|
+
if actual_params.respond_to? :should
|
181
|
+
actual_params.should == expected_params
|
182
|
+
else
|
183
|
+
assert_equal expected_params, actual_params
|
184
|
+
end
|
185
|
+
end
|
186
|
+
Then /^show me the page$/ do
|
187
|
+
save_and_open_page
|
188
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "minitest"
|
2
|
+
require "cucumber"
|
3
|
+
require "capybara/cucumber"
|
4
|
+
require "capybara-screenshot/cucumber"
|
5
|
+
require "selenium/webdriver"
|
6
|
+
|
7
|
+
config = YAML.load_file(File.join(Dir.pwd, "config.yml"))
|
8
|
+
|
9
|
+
driver_for_browser = {
|
10
|
+
"chrome" => :selenium_chrome_headless,
|
11
|
+
"firefox" => :selenium,
|
12
|
+
"safari" => :selenium_safari,
|
13
|
+
"edge" => :remote_edge,
|
14
|
+
"ie" => :remote_ie
|
15
|
+
}
|
16
|
+
|
17
|
+
driver = driver_for_browser[ENV["BROWSER"]] || config["driver"].to_sym
|
18
|
+
remote_ci_url = ENV["REMOTE_CI_URL"] || config["remote_ci_url"]
|
19
|
+
site = config["site"] || "http://localhost:3000"
|
20
|
+
|
21
|
+
if !remote_ci_url && (driver == :remote_edge || driver == :remote_ie)
|
22
|
+
raise "Error: Remote CI URL required for #{driver} is not set, set it in config.yml or with REMOTE_CI_URL env variable"
|
23
|
+
end
|
24
|
+
|
25
|
+
Capybara.register_driver :selenium_safari do |app|
|
26
|
+
Capybara::Selenium::Driver.new(app, browser: :safari)
|
27
|
+
end
|
28
|
+
|
29
|
+
Capybara.register_driver :remote_edge do |app|
|
30
|
+
Capybara::Selenium::Driver.new(app,
|
31
|
+
browser: :remote,
|
32
|
+
url: remote_ci_url,
|
33
|
+
desired_capabilities: Selenium::WebDriver::Remote::Capabilities.edge)
|
34
|
+
end
|
35
|
+
|
36
|
+
capabilities = Selenium::WebDriver::Remote::Capabilities.internet_explorer
|
37
|
+
capabilities.javascript_enabled = true
|
38
|
+
Capybara.register_driver :remote_ie do |app|
|
39
|
+
Capybara::Selenium::Driver.new(app,
|
40
|
+
browser: :remote,
|
41
|
+
url: remote_ci_url,
|
42
|
+
desired_capabilities: capabilities)
|
43
|
+
end
|
44
|
+
|
45
|
+
Capybara.default_driver = driver
|
46
|
+
Capybara.javascript_driver = driver
|
47
|
+
Capybara.run_server = false
|
48
|
+
Capybara.app_host = site
|
49
|
+
Capybara.save_path = File.join(Dir.pwd, "reports")
|
50
|
+
|
51
|
+
class TestAppWorld
|
52
|
+
include Capybara::DSL
|
53
|
+
include MiniTest::Assertions
|
54
|
+
end
|
55
|
+
|
56
|
+
World do
|
57
|
+
TestAppWorld.new
|
58
|
+
end
|
59
|
+
|
60
|
+
Capybara::Screenshot.class_eval do
|
61
|
+
register_driver(:selenium_chrome) do |driver, path|
|
62
|
+
driver.browser.save_screenshot(path)
|
63
|
+
end
|
64
|
+
|
65
|
+
register_driver(:selenium_chrome_headless) do |driver, path|
|
66
|
+
driver.browser.save_screenshot(path)
|
67
|
+
end
|
68
|
+
|
69
|
+
register_driver(:selenium_safari) do |driver, path|
|
70
|
+
driver.browser.save_screenshot(path)
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module HtmlSelectorsHelpers
|
2
|
+
# Maps a name to a selector. Used primarily by the
|
3
|
+
#
|
4
|
+
# When /^(.+) within (.+)$/ do |step, scope|
|
5
|
+
#
|
6
|
+
# step definitions in web_steps.rb
|
7
|
+
#
|
8
|
+
def selector_for(locator)
|
9
|
+
case locator
|
10
|
+
|
11
|
+
when "the page"
|
12
|
+
"html > body"
|
13
|
+
when "table's header"
|
14
|
+
"table tbody > tr th"
|
15
|
+
when /^paragraphs?$/
|
16
|
+
"p"
|
17
|
+
|
18
|
+
# Add more mappings here.
|
19
|
+
# Here is an example that pulls values out of the Regexp:
|
20
|
+
#
|
21
|
+
# when /^the (notice|error|info) flash$/
|
22
|
+
# ".flash.#{$1}"
|
23
|
+
|
24
|
+
# You can also return an array to use a different selector
|
25
|
+
# type, like:
|
26
|
+
#
|
27
|
+
# when /the header/
|
28
|
+
# [:xpath, "//header"]
|
29
|
+
|
30
|
+
# This allows you to provide a quoted selector as the scope
|
31
|
+
# for "within" steps as was previously the default for the
|
32
|
+
# web steps:
|
33
|
+
when /^"(.+)"$/
|
34
|
+
$1
|
35
|
+
|
36
|
+
else
|
37
|
+
raise "Can't find mapping from \"#{locator}\" to a selector.\n" +
|
38
|
+
"Now, go and add a mapping in #{__FILE__}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
World(HtmlSelectorsHelpers)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module NavigationHelpers
|
2
|
+
# Maps a name to a path. Used by the
|
3
|
+
#
|
4
|
+
# When /^I go to (.+)$/ do |page_name|
|
5
|
+
#
|
6
|
+
# step definition
|
7
|
+
#
|
8
|
+
def path_to(page_name)
|
9
|
+
case page_name
|
10
|
+
|
11
|
+
when /^the home\s?page$/
|
12
|
+
'/'
|
13
|
+
|
14
|
+
# Add more mappings here.
|
15
|
+
# Here is an example that pulls values out of the Regexp:
|
16
|
+
#
|
17
|
+
# when /^(.*)'s profile page$/i
|
18
|
+
# user_profile_path(User.find_by_login($1))
|
19
|
+
|
20
|
+
when /^the (.*) page$/
|
21
|
+
path_name = $1.split(/\s+/).join('_')
|
22
|
+
paths = YAML.load_file(File.join(Dir.pwd, "config.yml"))["paths"]
|
23
|
+
if path = paths[path_name]
|
24
|
+
path
|
25
|
+
else
|
26
|
+
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
|
27
|
+
"Now, go and add a mapping in config.yaml"
|
28
|
+
end
|
29
|
+
else
|
30
|
+
page_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
World(NavigationHelpers)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
begin
|
2
|
+
require 'site_prism'
|
3
|
+
|
4
|
+
SitePrism.configure do |config|
|
5
|
+
config.use_implicit_waits = true
|
6
|
+
end
|
7
|
+
|
8
|
+
Dir.glob(File.join(Dir.pwd, 'page_objects', '**','*.rb')).each do |f|
|
9
|
+
require f
|
10
|
+
end
|
11
|
+
|
12
|
+
module PageObjectsHelper
|
13
|
+
def visit_page(name, args = {}, &block)
|
14
|
+
build_page(name).tap do |page|
|
15
|
+
page.load(args)
|
16
|
+
block.call page if block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_page(name, args = {}, &block)
|
21
|
+
build_page(name).tap do |page|
|
22
|
+
expected = page.class.to_s.sub(/PageObjects::/, '')
|
23
|
+
expected += " (args: #{args})" if args.count > 0
|
24
|
+
assert page.displayed?(args), "expected to be on page '#{expected}', but was on #{page.current_path}"
|
25
|
+
block.call page if block
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_page(name)
|
30
|
+
name = name.to_s.camelize if name.is_a? Symbol
|
31
|
+
Object.const_get("#{name}").new
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
World(PageObjectsHelper)
|
36
|
+
rescue LoadError
|
37
|
+
end
|
data/qable.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "qable/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "qable"
|
8
|
+
spec.version = Qable::VERSION
|
9
|
+
spec.authors = ["Guillermo Iguaran"]
|
10
|
+
spec.email = ["guilleiguaran@gmail.com"]
|
11
|
+
spec.licenses = ['MIT']
|
12
|
+
spec.summary = %q{Qable acceptance testing framework}
|
13
|
+
spec.description = %q{Qable acceptance testig framework based in Cucumber/Capybara}
|
14
|
+
spec.homepage = "https://github.com/ableco/qable"
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "bundler", "~> 1.15"
|
23
|
+
spec.add_dependency "rake", "~> 12"
|
24
|
+
spec.add_dependency "minitest", "~> 5"
|
25
|
+
spec.add_dependency "cucumber", "~> 3.0"
|
26
|
+
spec.add_dependency "capybara", "~> 2.15"
|
27
|
+
spec.add_dependency "selenium-webdriver", "~> 3.7"
|
28
|
+
spec.add_dependency "capybara-screenshot", "~> 1.0"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Guillermo Iguaran
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: cucumber
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: capybara
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.15'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.15'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: selenium-webdriver
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.7'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.7'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: capybara-screenshot
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
111
|
+
description: Qable acceptance testig framework based in Cucumber/Capybara
|
112
|
+
email:
|
113
|
+
- guilleiguaran@gmail.com
|
114
|
+
executables:
|
115
|
+
- qable
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".travis.yml"
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- bin/console
|
126
|
+
- bin/qable
|
127
|
+
- bin/setup
|
128
|
+
- exe/qable
|
129
|
+
- lib/qable.rb
|
130
|
+
- lib/qable/generators/app/app_generator.rb
|
131
|
+
- lib/qable/generators/app/templates/Gemfile
|
132
|
+
- lib/qable/generators/app/templates/README.md
|
133
|
+
- lib/qable/generators/app/templates/Rakefile
|
134
|
+
- lib/qable/generators/app/templates/config.yml
|
135
|
+
- lib/qable/generators/app/templates/features/google_search.feature
|
136
|
+
- lib/qable/generators/app/templates/features/step_definitions/custom_steps.rb
|
137
|
+
- lib/qable/generators/app/templates/features/support/custom_matchers.rb
|
138
|
+
- lib/qable/generators/app/templates/features/support/env.rb
|
139
|
+
- lib/qable/generators/app/templates/features/support/hooks.rb
|
140
|
+
- lib/qable/generators/app/templates/gitignore
|
141
|
+
- lib/qable/step_definitions/web_steps.rb
|
142
|
+
- lib/qable/support.rb
|
143
|
+
- lib/qable/support/env.rb
|
144
|
+
- lib/qable/support/html_selectors_helpers.rb
|
145
|
+
- lib/qable/support/navigation_helpers.rb
|
146
|
+
- lib/qable/support/page_objects.rb
|
147
|
+
- lib/qable/version.rb
|
148
|
+
- qable.gemspec
|
149
|
+
- selenium-ie11-key.reg
|
150
|
+
homepage: https://github.com/ableco/qable
|
151
|
+
licenses:
|
152
|
+
- MIT
|
153
|
+
metadata: {}
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 2.6.11
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: Qable acceptance testing framework
|
174
|
+
test_files: []
|