qat-web 6.0.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/lib/capybara/core_ext.rb +7 -0
- data/lib/capybara/core_ext/capybara_error.rb +14 -0
- data/lib/capybara/core_ext/node/element.rb +35 -0
- data/lib/capybara/core_ext/selenium/node.rb +75 -0
- data/lib/headless/core_ext/random_display.rb +15 -0
- data/lib/qat/cli/plugins/web.rb +7 -0
- data/lib/qat/web.rb +12 -0
- data/lib/qat/web/browser.rb +21 -0
- data/lib/qat/web/browser/autoload.rb +22 -0
- data/lib/qat/web/browser/factory.rb +39 -0
- data/lib/qat/web/browser/firefox/harexporttrigger-0.5.0-beta.10.xpi +0 -0
- data/lib/qat/web/browser/firefox/loader/helper.rb +49 -0
- data/lib/qat/web/browser/html_dump.rb +46 -0
- data/lib/qat/web/browser/loader.rb +75 -0
- data/lib/qat/web/browser/profile.rb +92 -0
- data/lib/qat/web/browser/screenshot.rb +46 -0
- data/lib/qat/web/configuration.rb +46 -0
- data/lib/qat/web/cucumber.rb +19 -0
- data/lib/qat/web/drivers.rb +3 -0
- data/lib/qat/web/drivers/chrome.rb +5 -0
- data/lib/qat/web/drivers/default.rb +25 -0
- data/lib/qat/web/drivers/firefox.rb +6 -0
- data/lib/qat/web/drivers/firefox/har_exporter.rb +16 -0
- data/lib/qat/web/elements.rb +78 -0
- data/lib/qat/web/elements/base.rb +50 -0
- data/lib/qat/web/elements/collection.rb +16 -0
- data/lib/qat/web/elements/config.rb +19 -0
- data/lib/qat/web/elements/element.rb +16 -0
- data/lib/qat/web/elements/selector.rb +108 -0
- data/lib/qat/web/elements/waiters.rb +103 -0
- data/lib/qat/web/error.rb +14 -0
- data/lib/qat/web/error/enrichment.rb +14 -0
- data/lib/qat/web/exceptions.rb +15 -0
- data/lib/qat/web/finders.rb +49 -0
- data/lib/qat/web/hooks/common.rb +17 -0
- data/lib/qat/web/hooks/har_exporter.rb +32 -0
- data/lib/qat/web/hooks/html_dump.rb +21 -0
- data/lib/qat/web/hooks/screenshot.rb +20 -0
- data/lib/qat/web/page.rb +158 -0
- data/lib/qat/web/page/validators.rb +37 -0
- data/lib/qat/web/page_manager.rb +71 -0
- data/lib/qat/web/screen.rb +2 -0
- data/lib/qat/web/screen/autoload.rb +22 -0
- data/lib/qat/web/screen/factory.rb +68 -0
- data/lib/qat/web/screen/loader.rb +93 -0
- data/lib/qat/web/screen/wrapper.rb +96 -0
- data/lib/qat/web/version.rb +9 -0
- metadata +278 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'qat/web/configuration'
|
2
|
+
require 'active_support/core_ext/hash/keys'
|
3
|
+
|
4
|
+
module QAT
|
5
|
+
module Web
|
6
|
+
module Elements
|
7
|
+
# Helper methods for handling selectors and selector transformations
|
8
|
+
module Selector
|
9
|
+
include QAT::Web::Configuration
|
10
|
+
|
11
|
+
# Invalid Configuration Errors
|
12
|
+
class InvalidConfigurationError < StandardError
|
13
|
+
# Creates a new InvalidConfigurationError
|
14
|
+
# @param config [Hash] element selector configuration
|
15
|
+
def initialize(config)
|
16
|
+
super "Invalid configuration found:\n#{config.ai}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the selector from configuration
|
21
|
+
# @param config [Hash] element selector configuration
|
22
|
+
# @param args [Array] (Optional) Substitutions to the XPATH string base in $ syntax
|
23
|
+
# @return [Array] selector
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# xpath with ".//div[@class='ng-pristine' and text()='$0']//span[contains(text(), '$1')]"
|
27
|
+
# args with: ["Some Text", "More Text" ]
|
28
|
+
# The final output will be ".//div[@class='ng-pristine' and text()='Some Text']//span[contains(text(), 'More Text')]"
|
29
|
+
#
|
30
|
+
def selector(config, *args)
|
31
|
+
extract_selector(config, *args)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Extracts the ID or XPATH from the immediate node from the config
|
37
|
+
#
|
38
|
+
# @param config [Hash] element selector configuration
|
39
|
+
# @param args [Array] (Optional) Substitutions to the XPATH string base in $ syntax
|
40
|
+
# @return [Array] selector
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# xpath with ".//div[@class='ng-pristine' and text()='$0']//span[contains(text(), '$1')]"
|
44
|
+
# args with: ["Some Text", "More Text" ]
|
45
|
+
# The final output will be ".//div[@class='ng-pristine' and text()='Some Text']//span[contains(text(), 'More Text')]"
|
46
|
+
#
|
47
|
+
def extract_selector(config, *args)
|
48
|
+
type = fetch_type(config)
|
49
|
+
value = parse_value(config[type], *args)
|
50
|
+
opts = options(config)
|
51
|
+
save_config(type, value, opts)
|
52
|
+
if opts.any?
|
53
|
+
return type.to_sym, value, opts
|
54
|
+
else
|
55
|
+
return type.to_sym, value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the correct selector type from configuration
|
60
|
+
# @param config [Hash] element selector configuration
|
61
|
+
# @return [Symbol]
|
62
|
+
def fetch_type(config)
|
63
|
+
types = Capybara::Selector.all.keys & config.symbolize_keys.keys
|
64
|
+
|
65
|
+
raise InvalidConfigurationError.new config unless types.size == 1
|
66
|
+
|
67
|
+
types.first
|
68
|
+
end
|
69
|
+
|
70
|
+
# Parse the selector value for the given configuration through given arguments
|
71
|
+
# A list of substitutions will be applied from those arguments
|
72
|
+
# @param value [String] selector value
|
73
|
+
# @param args [Array] list of substitutions to apply
|
74
|
+
# @see #extract_selector
|
75
|
+
def parse_value(value, *args)
|
76
|
+
if args.empty?
|
77
|
+
value
|
78
|
+
else
|
79
|
+
args.each_with_index do |arg, index|
|
80
|
+
value = value.gsub("$#{index}", arg)
|
81
|
+
end
|
82
|
+
value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Return valid options for Capybara
|
87
|
+
# @param config [Hash] element selector configuration
|
88
|
+
# @return [Array]
|
89
|
+
def options(config)
|
90
|
+
config.symbolize_keys.select { |key, _| Capybara::Queries::SelectorQuery::VALID_KEYS.include?(key) }
|
91
|
+
end
|
92
|
+
|
93
|
+
# Saves the last configuration access
|
94
|
+
# @param type [Symbol] selector type
|
95
|
+
# @param value [String] selector value
|
96
|
+
# @param opts [Hash] selector options
|
97
|
+
# @return [Hash]
|
98
|
+
def save_config(type, value, opts)
|
99
|
+
config = { type => value }.merge(opts)
|
100
|
+
QAT::Web::Configuration.last_access = config
|
101
|
+
@last_access = config
|
102
|
+
end
|
103
|
+
|
104
|
+
extend self
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require_relative 'selector'
|
2
|
+
require_relative 'config'
|
3
|
+
require 'retriable'
|
4
|
+
require 'qat/logger'
|
5
|
+
|
6
|
+
module QAT
|
7
|
+
module Web
|
8
|
+
module Elements
|
9
|
+
# Helper methods for handling timeouts and wait periods
|
10
|
+
module Waiters
|
11
|
+
include QAT::Logger
|
12
|
+
include Selector
|
13
|
+
include Config
|
14
|
+
|
15
|
+
# Defines timeouts through a configuration file path
|
16
|
+
# @param path [String] path to timeouts configuration file
|
17
|
+
# @return [HashWithIndifferentAccess]
|
18
|
+
def timeouts_file(path)
|
19
|
+
raise(ArgumentError, "File '#{path}' does not exist!") unless File.exist?(path)
|
20
|
+
@timeouts_file = path
|
21
|
+
begin
|
22
|
+
config = YAML.load(File.read(@timeouts_file)) || {}
|
23
|
+
rescue Psych::SyntaxError
|
24
|
+
log.error "Failed to load file '#{@timeouts_file}'."
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
timeouts_config(config)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Defines timeouts through a configuration hash
|
31
|
+
# @param timeouts [Hash] timeouts configuration
|
32
|
+
# @return [HashWithIndifferentAccess]
|
33
|
+
def timeouts_config(timeouts)
|
34
|
+
valid_config?(timeouts, 'timeouts')
|
35
|
+
@timeouts = HashWithIndifferentAccess.new(timeouts)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the timeouts configuration
|
39
|
+
# @return [HashWithIndifferentAccess]
|
40
|
+
def timeouts
|
41
|
+
@timeouts
|
42
|
+
end
|
43
|
+
|
44
|
+
# Waits a maximum timeout time until an element is present on page
|
45
|
+
# @param selector [Hash] element selector
|
46
|
+
# @param timeout [Integer] maximum time to wait
|
47
|
+
def wait_until_present(selector, timeout)
|
48
|
+
type, value, options = build_selector(selector, { visible: false, wait: timeout })
|
49
|
+
has_selector?(type, value, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Waits a maximum timeout time until an element is visible on page
|
53
|
+
# @param selector [Hash] element selector
|
54
|
+
# @param timeout [Integer] maximum time to wait
|
55
|
+
def wait_until_visible(selector, timeout)
|
56
|
+
type, value, options = build_selector(selector, { visible: true, wait: timeout })
|
57
|
+
has_selector?(type, value, options)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Waits a maximum timeout time until an element is no longer present on page
|
61
|
+
# @param selector [Hash] element selector
|
62
|
+
# @param timeout [Integer] maximum time to wait
|
63
|
+
def wait_until_not_present(selector, timeout)
|
64
|
+
type, value, options = build_selector(selector, { wait: timeout })
|
65
|
+
has_no_selector?(type, value, options)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Waits a maximum timeout time until an element is no longer visible on page
|
69
|
+
# @param selector [Hash] element selector
|
70
|
+
# @param timeout [Integer] maximum time to wait
|
71
|
+
def wait_until_not_visible(selector, timeout)
|
72
|
+
type, value, options = build_selector(selector, { visible: false, wait: timeout })
|
73
|
+
has_no_selector?(type, value, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Generic wait method
|
77
|
+
# @param timeout [Integer] max time to wait
|
78
|
+
# @param klass [Class] (nil) an optional exception class to retry on error
|
79
|
+
# @yield
|
80
|
+
def wait_until(timeout, klass = nil, &block)
|
81
|
+
default_time = Capybara.default_max_wait_time
|
82
|
+
timeout ||= default_time
|
83
|
+
tries = timeout / default_time
|
84
|
+
exceptions = [Capybara::ElementNotFound, Capybara::ExpectationNotMet]
|
85
|
+
exceptions << klass if klass
|
86
|
+
Retriable.retriable(on: exceptions,
|
87
|
+
tries: tries.ceil,
|
88
|
+
base_interval: default_time) do
|
89
|
+
yield
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def build_selector(selector, options)
|
96
|
+
type, value, opts = *selector
|
97
|
+
options = opts.merge(options) if opts&.any?
|
98
|
+
[type, value, options]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative '../configuration'
|
2
|
+
# Module to handle exception enrichment.
|
3
|
+
# Should be include in the target exception class to be enriched in runtime.
|
4
|
+
module Enrichment
|
5
|
+
extend self
|
6
|
+
|
7
|
+
# Enrichs an exception message with the last configuration access in QAT::Web
|
8
|
+
#@param msg [String] exception message to be enriched
|
9
|
+
#@return [String]
|
10
|
+
def rich_msg(msg)
|
11
|
+
access = QAT::Web::Configuration.last_access
|
12
|
+
"#{msg}\nQAT::Web last access to configuration was '#{access}'"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'capybara'
|
2
|
+
require 'qat/web/error'
|
3
|
+
|
4
|
+
module QAT::Web
|
5
|
+
module Exceptions
|
6
|
+
GLOBAL = [
|
7
|
+
QAT::Web::Error,
|
8
|
+
Capybara::CapybaraError
|
9
|
+
]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
if defined?(Selenium)
|
14
|
+
QAT::Web::Exceptions::GLOBAL << Selenium::WebDriver::Error::WebDriverError
|
15
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
require_relative 'configuration'
|
3
|
+
require 'capybara'
|
4
|
+
|
5
|
+
module QAT::Web
|
6
|
+
#Module with custom finders based on configuration
|
7
|
+
#since 1.0.0
|
8
|
+
module Finders
|
9
|
+
include Configuration
|
10
|
+
#Alias to Capybara::Node::Finders#find method with parameter loading from configuration.
|
11
|
+
#An +Hash+ should be provided to calculate the correct parameters to pass to the original +find+ method.
|
12
|
+
#@param config [Hash] Configuration to extract parameters from
|
13
|
+
#@option config [String] :type Selector type (Capybara.default_selector)
|
14
|
+
#@option config [String] :value Selector value
|
15
|
+
#@see Capybara::Node::Finders#find
|
16
|
+
#@see Capybara::Queries::SelectorQuery
|
17
|
+
#@return [Capybara::Session] Current session
|
18
|
+
#@since 1.0.0
|
19
|
+
def find_from_configuration config
|
20
|
+
type, value, opts = parse_configuration config
|
21
|
+
page.find type, value, opts
|
22
|
+
end
|
23
|
+
|
24
|
+
#Alias to Capybara::Node::Finders#within method with parameter loading from configuration.
|
25
|
+
#An +Hash+ should be provided to calculate the correct parameters to pass to the original +within+ method.
|
26
|
+
#@param config [Hash] Configuration to extract parameters from
|
27
|
+
#@option config [String] :type Selector type (Capybara.default_selector)
|
28
|
+
#@option config [String] :value Selector value
|
29
|
+
#@see Capybara::Node::Finders#find
|
30
|
+
#@see Capybara::Queries::SelectorQuery
|
31
|
+
#@return [Capybara::Session] Current session
|
32
|
+
#@since 1.0.0
|
33
|
+
def within_from_configuration config, &block
|
34
|
+
type, value, opts = parse_configuration config
|
35
|
+
page.within type.to_sym, value, opts, &block
|
36
|
+
end
|
37
|
+
|
38
|
+
#Alias to Capybara::DSL base method
|
39
|
+
#@return [Capybara::Session] Current session
|
40
|
+
#@since 1.0.0
|
41
|
+
def page
|
42
|
+
Capybara.current_session
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Capybara::Node::Base.include QAT::Web::Finders
|
48
|
+
Capybara::Node::Simple.include QAT::Web::Finders
|
49
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module QAT
|
2
|
+
module Web
|
3
|
+
module Hooks
|
4
|
+
module Common
|
5
|
+
def scenario_tag(scenario)
|
6
|
+
tag = QAT[:current_test_run_id] if QAT.respond_to?(:[])
|
7
|
+
|
8
|
+
tag ||= Time.now.strftime("%H%M%S%L")
|
9
|
+
|
10
|
+
"#{scenario.name.parameterize}_#{tag}"
|
11
|
+
end
|
12
|
+
|
13
|
+
module_function :scenario_tag
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
After do |scenario|
|
2
|
+
if scenario.failed? and QAT::Web::Drivers::Firefox::HarExporter::EXCEPTIONS.include?(scenario.exception.class)
|
3
|
+
|
4
|
+
begin
|
5
|
+
log.info 'Saving HAR file'
|
6
|
+
|
7
|
+
Retriable.retriable(on: Selenium::WebDriver::Error::JavascriptError,
|
8
|
+
tries: 30,
|
9
|
+
base_interval: 5,
|
10
|
+
multiplier: 1,
|
11
|
+
rand_factor: 0,
|
12
|
+
on_retry: (proc do |exception, _scenario, _duration, _try|
|
13
|
+
log.warn 'Error saving HAR!'
|
14
|
+
log.debug exception
|
15
|
+
end)) do
|
16
|
+
result = Capybara.current_session.evaluate_script <<-JS
|
17
|
+
HAR.triggerExport({
|
18
|
+
token: '#{QAT::Web::Drivers::Firefox::HarExporter::TOKEN}', // Value of the token in your preferences
|
19
|
+
fileName: "http_requests_%d-%m-%yT%T", // T%T True if you want to also get HAR data as a string in the callback
|
20
|
+
}).then(result => {
|
21
|
+
// The local file is available now, result.data is null since options.getData wasn't set.
|
22
|
+
});
|
23
|
+
JS
|
24
|
+
end
|
25
|
+
|
26
|
+
log.info "Saved HAR file in configured folder."
|
27
|
+
rescue => e
|
28
|
+
log.error 'Could not save HAR file:'
|
29
|
+
log.error e
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
require 'qat/web/exceptions'
|
3
|
+
|
4
|
+
module QAT::Web
|
5
|
+
module Exceptions
|
6
|
+
HTML_DUMP = GLOBAL.dup
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Before do |scenario|
|
11
|
+
QAT::Web::Browser::HTMLDump.html_dump_path = File.join('public', "#{QAT::Web::Hooks::Common.scenario_tag(scenario)}.html")
|
12
|
+
end
|
13
|
+
|
14
|
+
After do |scenario|
|
15
|
+
if scenario.failed?
|
16
|
+
if QAT::Web::Exceptions::HTML_DUMP.any? { |exception| scenario.exception.kind_of?(exception) }
|
17
|
+
# Embeds an existing HTML dump to Cucumber's HTML report
|
18
|
+
embed(QAT::Web::Browser::HTMLDump.take_html_dump, 'text/plain', 'HTML dump')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
require 'qat/web/exceptions'
|
3
|
+
|
4
|
+
module QAT::Web
|
5
|
+
module Exceptions
|
6
|
+
SCREENSHOT = GLOBAL.dup
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Before do |scenario|
|
11
|
+
QAT::Web::Browser::Screenshot.screenshot_path = File.join('public', "#{QAT::Web::Hooks::Common.scenario_tag(scenario)}.png")
|
12
|
+
end
|
13
|
+
|
14
|
+
After do |scenario|
|
15
|
+
if scenario.failed?
|
16
|
+
if QAT::Web::Exceptions::SCREENSHOT.any? { |exception| scenario.exception.kind_of?(exception) }
|
17
|
+
embed QAT::Web::Browser::Screenshot.take_screenshot, 'image/png', 'Screenshot'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/qat/web/page.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
require_relative 'elements'
|
3
|
+
require_relative 'page/validators'
|
4
|
+
|
5
|
+
module QAT::Web
|
6
|
+
|
7
|
+
#Class to represent a Web Page. Works based on a DSL to write user friendly and powerful transition models.
|
8
|
+
#Two class methods are provided by this class, in order to allow the mapping of getters for page values, and also map
|
9
|
+
#page transitions.
|
10
|
+
#The use of Capybara::DSL in the implementation is recommended.
|
11
|
+
# @example Sample Page Object implementation for http://localhost:8090/example
|
12
|
+
# class ExamplePage < QAT::Web::Page
|
13
|
+
# include Capybara::DSL
|
14
|
+
#
|
15
|
+
# def initialize
|
16
|
+
# visit 'http://localhost:8090/example'
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# get_value :title do
|
20
|
+
# find 'h1'
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# action :more_information, returns: ExampleInformationPage do
|
24
|
+
# click_link 'More information...'
|
25
|
+
# ExampleInformationPage.new
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# current_page = ExamplePage.new
|
30
|
+
# current_page.title # 'Example Domain'
|
31
|
+
# current_page = current_page.more_information # ExampleInformationPage instance
|
32
|
+
#
|
33
|
+
#@see http://www.rubydoc.info/github/jnicklas/capybara/master/Capybara/DSL Capybara::DSL
|
34
|
+
#@abstract
|
35
|
+
#@since 1.0.0
|
36
|
+
class Page
|
37
|
+
include Elements
|
38
|
+
extend Elements
|
39
|
+
extend Elements::Waiters
|
40
|
+
|
41
|
+
class << self
|
42
|
+
include Validators
|
43
|
+
|
44
|
+
#@return [Array<Symbol>] List of value getter functions
|
45
|
+
def values
|
46
|
+
@values ||= []
|
47
|
+
if superclass.ancestors.include? QAT::Web::Page
|
48
|
+
@values + superclass.values
|
49
|
+
else
|
50
|
+
@values
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
#@return [Hash<Symbol, Array<QAT::Web::Page>>] List of page actions and respective transition return types
|
56
|
+
def actions
|
57
|
+
@actions ||= {}
|
58
|
+
if superclass.ancestors.include? QAT::Web::Page
|
59
|
+
superclass.actions.merge @actions
|
60
|
+
else
|
61
|
+
@actions
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#Define a new method to get a value from a page. A new instance method will be defined with the given name
|
66
|
+
#parameter, and with the block as the method's code to be executed. The name of the method will be added to {QAT::Web::Page#values}
|
67
|
+
#@param name [String/Symbol] Name of the funcion to be defined
|
68
|
+
#@yield Block of code to define the getter method. The block will only be executed then the function defined by "name" is called
|
69
|
+
def get_value name, &block
|
70
|
+
name = name.to_sym
|
71
|
+
define_method name, &block
|
72
|
+
@values ||= []
|
73
|
+
@values << name
|
74
|
+
end
|
75
|
+
|
76
|
+
#Define a new method to represent a possible page transition to another page object controller. A new instance method
|
77
|
+
#will be defined with the given name parameter, and with the block as the method's code to be executed.
|
78
|
+
#Additionally, all possible return types must be delacred in the :returns key in the opts parameter.
|
79
|
+
#All return types must be implementarions of QAT::Web::Page.
|
80
|
+
#@param name [String/Symbol] Name of the funcion to be defined
|
81
|
+
#@param opts [Hash] Options hash
|
82
|
+
#@option opts [Class/Array<Class>] :returns Sublass or list of subclasses of QAT::Web::Page that can be returned by the method definition
|
83
|
+
#@yield Block of code to define the getter method. The block will only be executed then the function defined by "name" is called
|
84
|
+
#@yieldreturn [QAT::Web::Page] Instance of the destination page object
|
85
|
+
def action name, opts, &block
|
86
|
+
|
87
|
+
raise TypeError.new 'The opts parameter should be an Hash with a :returns key' unless opts.is_a? Hash
|
88
|
+
|
89
|
+
return_value = validate_return_value(opts[:returns])
|
90
|
+
|
91
|
+
name = name.to_sym
|
92
|
+
define_method name, &block
|
93
|
+
@actions ||= {}
|
94
|
+
@actions[name] = return_value
|
95
|
+
end
|
96
|
+
|
97
|
+
# Loads elements configuration from a configuration file given a file path
|
98
|
+
# @param path [String] path to configuration file
|
99
|
+
# @return [HashWithIndifferentAccess]
|
100
|
+
def elements_file(path)
|
101
|
+
raise(ArgumentError, "File '#{path}' does not exist!") unless File.exist?(path)
|
102
|
+
@elements_file = path
|
103
|
+
elements_config(load_elements_file(@elements_file))
|
104
|
+
end
|
105
|
+
|
106
|
+
# Defines elements through a configuration hash
|
107
|
+
# @param elements [Hash] elements configuration
|
108
|
+
# @return [HashWithIndifferentAccess]
|
109
|
+
def elements_config(elements)
|
110
|
+
valid_config?(elements, 'elements')
|
111
|
+
@elements = HashWithIndifferentAccess.new(elements)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns the elements configuration
|
115
|
+
# @return [HashWithIndifferentAccess]
|
116
|
+
def elements
|
117
|
+
@elements
|
118
|
+
end
|
119
|
+
|
120
|
+
# Defines a web element accessor identified through the given name and configuration
|
121
|
+
# Auxiliary methods are also dynamically defined such as the element acessor, waiters and the configuration accessor
|
122
|
+
# @param args [Array] One or two arguments are expected. The first argument is the element *name*
|
123
|
+
# and the second an optional *configuration*.
|
124
|
+
# If none is given, it will be automatically loaded from the loaded configuration by the element name
|
125
|
+
# @see Capybara::Node::Finders#find
|
126
|
+
def web_element(*args)
|
127
|
+
element = QAT::Web::Elements::Element.new(elements, *args)
|
128
|
+
define_web_element_methods(element)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Defines a list of web element accessors identified through the given names
|
132
|
+
# Configuration will be automatically loaded from the loaded configuration by element name
|
133
|
+
# Auxiliary methods are also dynamically defined such as the element acessor, waiters and the configuration accessor
|
134
|
+
# @param elements [Array|Symbol] list of names to load elements
|
135
|
+
# @see Capybara::Node::Finders#find
|
136
|
+
def web_elements(*elements)
|
137
|
+
elements.each { |element| web_element(element) }
|
138
|
+
end
|
139
|
+
|
140
|
+
# Defines a collection of web elements identified through a given name and configuration
|
141
|
+
# Auxiliary methods are also dynamically defined such as the element acessor, waiters and the configuration accessor
|
142
|
+
# @param args [Array] One or two arguments are expected. The first argument is the element *name*
|
143
|
+
# and the second an optional *configuration*.
|
144
|
+
# If none is given, it will be automatically loaded from the loaded configuration by the element name
|
145
|
+
# @see Capybara::Node::Finders#all
|
146
|
+
def web_collection(*args)
|
147
|
+
collection = QAT::Web::Elements::Collection.new(elements, *args)
|
148
|
+
define_web_element_methods(collection)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns the elements configuration
|
153
|
+
# @return [HashWithIndifferentAccess]
|
154
|
+
def elements
|
155
|
+
self.class.elements
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|