howitzer 2.2.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -1
- data/LICENSE +1 -1
- data/README.md +16 -17
- data/generators/base_generator.rb +4 -6
- data/generators/config/config_generator.rb +2 -4
- data/generators/config/templates/boot.rb +1 -1
- data/generators/config/templates/capybara.rb +3 -5
- data/generators/config/templates/default.yml +19 -20
- data/generators/config/templates/drivers/browserstack.rb +31 -4
- data/generators/config/templates/drivers/crossbrowsertesting.rb +9 -11
- data/generators/config/templates/drivers/headless_chrome.rb +1 -1
- data/generators/config/templates/drivers/headless_firefox.rb +1 -1
- data/generators/config/templates/drivers/lambdatest.rb +30 -0
- data/generators/config/templates/drivers/sauce.rb +30 -2
- data/generators/config/templates/drivers/selenium.rb +1 -1
- data/generators/config/templates/drivers/selenium_grid.rb +3 -3
- data/generators/config/templates/drivers/testingbot.rb +29 -2
- data/generators/cucumber/templates/env.rb +1 -1
- data/generators/cucumber/templates/hooks.rb +9 -3
- data/generators/cucumber/templates/transformers.rb +1 -1
- data/generators/prerequisites/templates/factory_bot.rb +1 -1
- data/generators/root/templates/Gemfile.erb +4 -14
- data/generators/rspec/templates/spec_helper.rb +5 -5
- data/generators/turnip/templates/spec_helper.rb +5 -5
- data/generators/web/templates/example_page.rb +1 -1
- data/lib/howitzer/cache.rb +1 -1
- data/lib/howitzer/capybara_helpers.rb +46 -9
- data/lib/howitzer/email.rb +2 -2
- data/lib/howitzer/exceptions.rb +21 -21
- data/lib/howitzer/gmail_api/client.rb +13 -4
- data/lib/howitzer/log.rb +6 -6
- data/lib/howitzer/mail_adapters/mailgun.rb +1 -1
- data/lib/howitzer/mail_adapters/mailtrap.rb +3 -3
- data/lib/howitzer/mail_adapters/onesecmail.rb +80 -0
- data/lib/howitzer/mail_adapters/testmail.rb +102 -0
- data/lib/howitzer/mailgun_api/client.rb +3 -2
- data/lib/howitzer/mailgun_api/response.rb +1 -2
- data/lib/howitzer/mailtrap_api/client.rb +19 -1
- data/lib/howitzer/meta/actions.rb +13 -16
- data/lib/howitzer/meta/element.rb +12 -10
- data/lib/howitzer/onesecmail_api/client.rb +44 -0
- data/lib/howitzer/onesecmail_api.rb +7 -0
- data/lib/howitzer/testmail_api/client.rb +44 -0
- data/lib/howitzer/testmail_api.rb +7 -0
- data/lib/howitzer/utils/string_extensions.rb +6 -2
- data/lib/howitzer/version.rb +1 -1
- data/lib/howitzer/web/base_section.rb +1 -1
- data/lib/howitzer/web/capybara_methods_proxy.rb +11 -5
- data/lib/howitzer/web/element_dsl.rb +104 -45
- data/lib/howitzer/web/iframe_dsl.rb +2 -2
- data/lib/howitzer/web/page.rb +4 -14
- data/lib/howitzer/web/page_dsl.rb +15 -6
- data/lib/howitzer/web/page_validator.rb +25 -26
- data/lib/howitzer/web/section.rb +5 -2
- data/lib/howitzer/web/section_dsl.rb +64 -30
- data/lib/howitzer.rb +2 -2
- metadata +29 -165
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -14
- data/.rspec +0 -3
- data/.rubocop.yml +0 -60
- data/.ruby-gemset +0 -1
- data/.travis.yml +0 -8
- data/Gemfile +0 -14
- data/ISSUE_TEMPLATE.md +0 -16
- data/MAINTENANCE.md +0 -32
- data/Rakefile +0 -38
- data/features/cli_help.feature +0 -31
- data/features/cli_new.feature +0 -393
- data/features/cli_unknown.feature +0 -17
- data/features/cli_update.feature +0 -223
- data/features/cli_version.feature +0 -14
- data/features/step_definitions/common_steps.rb +0 -34
- data/features/support/env.rb +0 -1
- data/generators/config/templates/drivers/appium.rb +0 -25
- data/generators/config/templates/drivers/poltergeist.rb +0 -11
- data/generators/config/templates/drivers/webkit.rb +0 -6
- data/generators/root/templates/.gitignore +0 -21
- data/generators/root/templates/.rubocop.yml.erb +0 -56
- data/generators/turnip/templates/.rspec +0 -1
- data/howitzer.gemspec +0 -39
- data/lib/howitzer/mail_adapters/debugmail.rb +0 -0
- data/spec/config/custom.yml +0 -9
- data/spec/spec_helper.rb +0 -73
- data/spec/support/generator_helper.rb +0 -21
- data/spec/support/logger_helper.rb +0 -13
- data/spec/support/shared_examples/capybara_context_holder.rb +0 -33
- data/spec/support/shared_examples/capybara_methods_proxy.rb +0 -94
- data/spec/support/shared_examples/dynamic_section_methods.rb +0 -35
- data/spec/support/shared_examples/element_dsl.rb +0 -242
- data/spec/support/shared_examples/meta_highlight_xpath.rb +0 -41
- data/spec/unit/generators/base_generator_spec.rb +0 -283
- data/spec/unit/generators/config_generator_spec.rb +0 -61
- data/spec/unit/generators/cucumber_generator_spec.rb +0 -62
- data/spec/unit/generators/emails_generator_spec.rb +0 -35
- data/spec/unit/generators/prerequisites_generator_spec.rb +0 -53
- data/spec/unit/generators/root_generator_spec.rb +0 -86
- data/spec/unit/generators/rspec_generator_spec.rb +0 -36
- data/spec/unit/generators/tasks_generator_spec.rb +0 -31
- data/spec/unit/generators/templates/cucumber_spec.rb +0 -97
- data/spec/unit/generators/templates/rspec_spec.rb +0 -88
- data/spec/unit/generators/templates/turnip_spec.rb +0 -98
- data/spec/unit/generators/turnip_generator_spec.rb +0 -52
- data/spec/unit/generators/web_generator_spec.rb +0 -52
- data/spec/unit/lib/cache_spec.rb +0 -85
- data/spec/unit/lib/capybara_helpers_spec.rb +0 -730
- data/spec/unit/lib/email_spec.rb +0 -186
- data/spec/unit/lib/gmail_api/client_spec.rb +0 -26
- data/spec/unit/lib/howitzer_spec.rb +0 -92
- data/spec/unit/lib/init_spec.rb +0 -2
- data/spec/unit/lib/log_spec.rb +0 -122
- data/spec/unit/lib/mail_adapters/abstract_spec.rb +0 -62
- data/spec/unit/lib/mail_adapters/gmail_spec.rb +0 -128
- data/spec/unit/lib/mail_adapters/mailgun_spec.rb +0 -158
- data/spec/unit/lib/mail_adapters/mailtrap_spec.rb +0 -130
- data/spec/unit/lib/mailgun_api/client_spec.rb +0 -80
- data/spec/unit/lib/mailgun_api/connector_spec.rb +0 -54
- data/spec/unit/lib/mailgun_api/response_spec.rb +0 -28
- data/spec/unit/lib/mailtrap_api/client_spec.rb +0 -67
- data/spec/unit/lib/meta/element_spec.rb +0 -59
- data/spec/unit/lib/meta/entry_spec.rb +0 -77
- data/spec/unit/lib/meta/iframe_spec.rb +0 -66
- data/spec/unit/lib/meta/section_spec.rb +0 -43
- data/spec/unit/lib/utils/string_extensions_spec.rb +0 -77
- data/spec/unit/lib/web/base_section_spec.rb +0 -43
- data/spec/unit/lib/web/element_dsl_spec.rb +0 -31
- data/spec/unit/lib/web/iframe_dsl_spec.rb +0 -203
- data/spec/unit/lib/web/page_dsl_spec.rb +0 -74
- data/spec/unit/lib/web/page_spec.rb +0 -385
- data/spec/unit/lib/web/page_validator_spec.rb +0 -276
- data/spec/unit/lib/web/section_dsl_spec.rb +0 -165
- data/spec/unit/lib/web/section_spec.rb +0 -70
- data/spec/unit/version_spec.rb +0 -8
@@ -3,23 +3,26 @@ module Howitzer
|
|
3
3
|
# Module with utility actions for elements
|
4
4
|
module Actions
|
5
5
|
# Highlights element with red border on the page
|
6
|
-
# @param args [Array] arguments for elements described with lambda locators
|
7
|
-
#
|
8
|
-
def highlight(*args)
|
9
|
-
if xpath(*args).blank?
|
6
|
+
# @param args [Array] arguments for elements described with lambda locators
|
7
|
+
# @param options [Hash] original Capybara options. For details, see `Capybara::Node::Finders#all`
|
8
|
+
def highlight(*args, **options)
|
9
|
+
if xpath(*args, **options).blank?
|
10
10
|
Howitzer::Log.debug("Element #{name} not found on the page")
|
11
11
|
return
|
12
12
|
end
|
13
|
-
|
14
|
-
|
13
|
+
element = escape(xpath(*args, **options))
|
14
|
+
context.execute_script(
|
15
|
+
"document.evaluate('#{element}', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)." \
|
16
|
+
'singleNodeValue.style.border = "thick solid red"'
|
17
|
+
)
|
15
18
|
end
|
16
19
|
|
17
20
|
# Returns xpath for the element
|
18
|
-
# @param args [Array] arguments for elements described with lambda locators
|
19
|
-
#
|
21
|
+
# @param args [Array] arguments for elements described with lambda locators
|
22
|
+
# @param options [Hash] original Capybara options. For details, see `Capybara::Node::Finders#all`
|
20
23
|
# @return [String, nil]
|
21
|
-
def xpath(*args)
|
22
|
-
capybara_element(*args).try(:path)
|
24
|
+
def xpath(*args, **options)
|
25
|
+
capybara_element(*args, **options).try(:path)
|
23
26
|
end
|
24
27
|
|
25
28
|
private
|
@@ -27,12 +30,6 @@ module Howitzer
|
|
27
30
|
def escape(xpath)
|
28
31
|
xpath.gsub(/(['"])/, '\\\\\\1')
|
29
32
|
end
|
30
|
-
|
31
|
-
def convert_args(args)
|
32
|
-
new_args = []
|
33
|
-
params = args.reject { |v| new_args << v if v.is_a?(Hash) }
|
34
|
-
[params, new_args.reduce(:merge)].flatten
|
35
|
-
end
|
36
33
|
end
|
37
34
|
end
|
38
35
|
end
|
@@ -14,22 +14,24 @@ module Howitzer
|
|
14
14
|
end
|
15
15
|
|
16
16
|
# Finds all instances of element on the page and returns them as array of capybara elements
|
17
|
-
# @param args [Array] arguments for elements described with lambda locators
|
18
|
-
#
|
17
|
+
# @param args [Array] arguments for elements described with lambda locators
|
18
|
+
# @param options [Hash] original Capybara options. For details, see `Capybara::Node::Finders#all`
|
19
19
|
# @return [Array]
|
20
|
-
def capybara_elements(*args)
|
21
|
-
|
20
|
+
def capybara_elements(*args, **options)
|
21
|
+
if options.present?
|
22
|
+
context.send("#{name}_elements", *args, **options)
|
23
|
+
else
|
24
|
+
context.send("#{name}_elements", *args)
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
# Finds element on the page and returns as a capybara element
|
25
|
-
# @param args [Array] arguments for elements described with lambda locators
|
26
|
-
#
|
29
|
+
# @param args [Array] arguments for elements described with lambda locators
|
30
|
+
# @param options [Hash] original Capybara options. For details, see `Capybara::Node::Finders#all`
|
27
31
|
# @param wait [Integer] wait time for element search
|
28
32
|
# @return [Capybara::Node::Element, nil]
|
29
|
-
def capybara_element(*args, wait: 0)
|
30
|
-
args
|
31
|
-
args = convert_args(args)
|
32
|
-
context.send("#{name}_element", *args)
|
33
|
+
def capybara_element(*args, wait: 0, **options)
|
34
|
+
context.send("#{name}_element", *args, **options.merge(match: :first, wait: wait))
|
33
35
|
rescue Capybara::ElementNotFound
|
34
36
|
nil
|
35
37
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
module Howitzer
|
5
|
+
module OnesecmailApi
|
6
|
+
# A Onesecmail::Client object is used to communicate with the 1secMail API.
|
7
|
+
class Client
|
8
|
+
BASE_URL = 'https://www.1secmail.com/api/v1/'.freeze # :nodoc:
|
9
|
+
|
10
|
+
# Finds message according to given parameters
|
11
|
+
#
|
12
|
+
# @param recipient [String] this is recipient mail address for message filtering
|
13
|
+
# @param subject [String] this is subject of the message to filter particular message
|
14
|
+
# @return [Hash] json message parsed to ruby hash
|
15
|
+
|
16
|
+
def find_message(recipient, subject)
|
17
|
+
messages = filter_by_subject(recipient[/[^@]+/], subject)
|
18
|
+
latest_message(messages)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def messages(recipient_name)
|
24
|
+
JSON.parse(RestClient.get("#{BASE_URL}?action=getMessages&login=#{recipient_name}" \
|
25
|
+
"&domain=#{Howitzer.onesecmail_domain}"))
|
26
|
+
end
|
27
|
+
|
28
|
+
def latest_message(messages)
|
29
|
+
messages[0]
|
30
|
+
end
|
31
|
+
|
32
|
+
def filter_by_subject(recipient_name, subject)
|
33
|
+
result_messages = []
|
34
|
+
messages(recipient_name).each do |msg|
|
35
|
+
if msg['subject'] == subject
|
36
|
+
result_messages << JSON.parse(RestClient.get("#{BASE_URL}?action=readMessage&login=#{recipient_name}" \
|
37
|
+
"&domain=#{Howitzer.onesecmail_domain}&id=#{msg['id']}"))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
result_messages
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
module Howitzer
|
5
|
+
module TestmailApi
|
6
|
+
# A Testmail::Client object is used to communicate with the testmail.app API.
|
7
|
+
class Client
|
8
|
+
BASE_URL = "https://api.testmail.app/api/json?apikey=#{Howitzer.testmail_api_key}" \
|
9
|
+
"&namespace=#{Howitzer.testmail_namespace}".freeze # :nodoc:
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@api_token = Howitzer.testmail_api_key
|
13
|
+
end
|
14
|
+
|
15
|
+
# Finds message according to given parameters
|
16
|
+
#
|
17
|
+
# @param recipient [String] this is recipient mail address for message filtering
|
18
|
+
# @param subject [String] this is subject of the message to filter particular message
|
19
|
+
# @return [Hash] json message parsed to ruby hash
|
20
|
+
|
21
|
+
def find_message(recipient, subject)
|
22
|
+
recipient = recipient.gsub(/.*\.([^@]+)@.*/, '\1')
|
23
|
+
messages = filter_by_subject(messages(recipient), subject)
|
24
|
+
latest_message(messages)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def messages(recipient)
|
30
|
+
JSON.parse(RestClient.get("#{BASE_URL}&tag=#{recipient}"))
|
31
|
+
end
|
32
|
+
|
33
|
+
def latest_message(messages)
|
34
|
+
messages[0]
|
35
|
+
end
|
36
|
+
|
37
|
+
def filter_by_subject(messages, subject)
|
38
|
+
result_messages = []
|
39
|
+
messages['emails'].each { |msg| result_messages << msg if msg['subject'] == subject }
|
40
|
+
result_messages
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -7,8 +7,12 @@ module Howitzer
|
|
7
7
|
# 'home'.open #=> HomePage.open
|
8
8
|
# @see Howitzer::Web::Page.open
|
9
9
|
|
10
|
-
def open(*args)
|
11
|
-
|
10
|
+
def open(*args, **options)
|
11
|
+
if options.present?
|
12
|
+
as_page_class.open(*args, **options)
|
13
|
+
else
|
14
|
+
as_page_class.open(*args)
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
# Returns an instantiated page by name
|
data/lib/howitzer/version.rb
CHANGED
@@ -3,7 +3,7 @@ require 'active_support'
|
|
3
3
|
require 'active_support/core_ext'
|
4
4
|
|
5
5
|
# Remove this monkey patch after fixing the bugs in selenium-webdriver / capybara
|
6
|
-
|
6
|
+
# :nocov:
|
7
7
|
class Capybara::Selenium::Driver # rubocop:disable Style/ClassAndModuleChildren
|
8
8
|
#
|
9
9
|
# https://github.com/teamcapybara/capybara/issues/1845
|
@@ -13,7 +13,7 @@ class Capybara::Selenium::Driver # rubocop:disable Style/ClassAndModuleChildren
|
|
13
13
|
find_xpath('/html/head/title').map { |n| n[:text] }.first.to_s
|
14
14
|
end
|
15
15
|
|
16
|
-
# Known issue, works differently for
|
16
|
+
# Known issue, works differently for real browsers
|
17
17
|
# https://github.com/seleniumhq/selenium/issues/1727
|
18
18
|
def current_url
|
19
19
|
return browser.current_url unless within_frame?
|
@@ -27,13 +27,13 @@ class Capybara::Selenium::Driver # rubocop:disable Style/ClassAndModuleChildren
|
|
27
27
|
!(@frame_handles.blank? || @frame_handles[browser.window_handle].blank?)
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
30
|
+
# :nocov:
|
31
31
|
|
32
32
|
module Howitzer
|
33
33
|
module Web
|
34
34
|
# This module proxies required original capybara methods to recipient
|
35
35
|
module CapybaraMethodsProxy
|
36
|
-
PROXIED_CAPYBARA_METHODS = Capybara::Session::SESSION_METHODS +
|
36
|
+
PROXIED_CAPYBARA_METHODS = Capybara::Session::SESSION_METHODS + # :nodoc:
|
37
37
|
Capybara::Session::MODAL_METHODS +
|
38
38
|
%i[driver text]
|
39
39
|
|
@@ -41,7 +41,13 @@ module Howitzer
|
|
41
41
|
# Instead of including Capybara::DSL module, we proxy most interesting Capybara methods and
|
42
42
|
# prevent using extra methods which can potentially broke main principles and framework concept
|
43
43
|
PROXIED_CAPYBARA_METHODS.each do |method|
|
44
|
-
define_method(method)
|
44
|
+
define_method(method) do |*args, **options, &block|
|
45
|
+
if options.present?
|
46
|
+
Capybara.current_session.send(method, *args, **options, &block)
|
47
|
+
else
|
48
|
+
Capybara.current_session.send(method, *args, &block)
|
49
|
+
end
|
50
|
+
end
|
45
51
|
end
|
46
52
|
|
47
53
|
# Accepts or declines JS alert box by given flag
|
@@ -3,40 +3,68 @@ module Howitzer
|
|
3
3
|
module Web
|
4
4
|
# This module combines element dsl methods
|
5
5
|
module ElementDsl
|
6
|
+
# This module holds element helper methods
|
7
|
+
module Helpers
|
8
|
+
private
|
9
|
+
|
10
|
+
def lambda_args(*args, **keyword_args)
|
11
|
+
{
|
12
|
+
lambda_args: {
|
13
|
+
args: args,
|
14
|
+
keyword_args: keyword_args
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
6
20
|
include CapybaraContextHolder
|
21
|
+
include Helpers
|
7
22
|
|
8
|
-
def self.included(base)
|
23
|
+
def self.included(base) # :nodoc:
|
9
24
|
base.extend(ClassMethods)
|
10
25
|
end
|
11
26
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
27
|
+
def convert_arguments(args, options, block_args, block_options)
|
28
|
+
conv_args = args.map { |el| el.is_a?(Proc) ? proc_to_selector(el, block_args, block_options) : el }
|
29
|
+
args_options = pop_options_from_array(conv_args)
|
30
|
+
block_args_options = pop_options_from_array(block_args)
|
31
|
+
conv_options = [args_options, options, block_args_options, block_options].map do |el|
|
32
|
+
el.transform_keys(&:to_sym)
|
33
|
+
end.reduce(&:merge).except(:lambda_args)
|
34
|
+
[conv_args, conv_options]
|
35
|
+
end
|
18
36
|
|
19
|
-
|
37
|
+
def proc_to_selector(proc, block_args, block_options)
|
38
|
+
lambda_args = extract_lambda_args(block_args, block_options)
|
39
|
+
if lambda_args
|
40
|
+
if lambda_args[:keyword_args].present?
|
41
|
+
proc.call(*lambda_args[:args], **lambda_args[:keyword_args])
|
42
|
+
else
|
43
|
+
proc.call(*lambda_args[:args])
|
44
|
+
end
|
45
|
+
else
|
46
|
+
puts "WARNING! Passing lambda arguments with element options is deprecated.\n" \
|
47
|
+
"Please use 'lambda_args' method, for example: foo_element(lambda_args(title: 'Example'), wait: 10)"
|
48
|
+
proc.call(*block_args.shift(proc.arity))
|
20
49
|
end
|
21
|
-
args << options unless options.blank?
|
22
|
-
args
|
23
50
|
end
|
24
51
|
|
25
|
-
def
|
26
|
-
|
27
|
-
new_params, params_hash = extract_element_options(params)
|
28
|
-
[new_args, new_params, args_hash.merge(params_hash)]
|
52
|
+
def extract_lambda_args(block_args, block_options)
|
53
|
+
(block_args.first.is_a?(Hash) && block_args.first[:lambda_args]) || block_options[:lambda_args]
|
29
54
|
end
|
30
55
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
56
|
+
def pop_options_from_array(value)
|
57
|
+
if value.last.is_a?(Hash) && !value.last.key?(:lambda_args)
|
58
|
+
value.pop
|
59
|
+
else
|
60
|
+
{}
|
61
|
+
end
|
36
62
|
end
|
37
63
|
|
38
|
-
# This module holds element dsl methods
|
64
|
+
# This module holds element dsl methods
|
39
65
|
module ClassMethods
|
66
|
+
include Helpers
|
67
|
+
|
40
68
|
protected
|
41
69
|
|
42
70
|
# Creates a group of methods to interact with described HTML element(s) on page
|
@@ -57,6 +85,7 @@ module Howitzer
|
|
57
85
|
# <b>has_no_<em>element_name</em>_element?</b> - equals capybara #has_no_selector(...) method
|
58
86
|
# @param name [Symbol, String] an unique element name
|
59
87
|
# @param args [Array] original Capybara arguments. For details, see `Capybara::Node::Finders#all`.
|
88
|
+
# @param options [Hash] original Capybara options. For details, see `Capybara::Node::Finders#all`.
|
60
89
|
# @example Using in a page class
|
61
90
|
# class HomePage < Howitzer::Web::Page
|
62
91
|
# element :top_panel, '.top'
|
@@ -93,14 +122,14 @@ module Howitzer
|
|
93
122
|
# @raise [BadElementParamsError] if wrong element arguments
|
94
123
|
# @!visibility public
|
95
124
|
|
96
|
-
def element(name, *args)
|
125
|
+
def element(name, *args, **options)
|
97
126
|
validate_arguments!(args)
|
98
|
-
define_element(name, args)
|
99
|
-
define_elements(name, args)
|
100
|
-
define_wait_for_element(name, args)
|
101
|
-
define_within_element(name, args)
|
102
|
-
define_has_element(name, args)
|
103
|
-
define_has_no_element(name, args)
|
127
|
+
define_element(name, args, options)
|
128
|
+
define_elements(name, args, options)
|
129
|
+
define_wait_for_element(name, args, options)
|
130
|
+
define_within_element(name, args, options)
|
131
|
+
define_has_element(name, args, options)
|
132
|
+
define_has_no_element(name, args, options)
|
104
133
|
end
|
105
134
|
|
106
135
|
private
|
@@ -111,31 +140,51 @@ module Howitzer
|
|
111
140
|
raise Howitzer::BadElementParamsError, 'Using more than 1 proc in arguments is forbidden'
|
112
141
|
end
|
113
142
|
|
114
|
-
def define_element(name, args)
|
115
|
-
define_method("#{name}_element") do |*block_args|
|
116
|
-
|
143
|
+
def define_element(name, args, options)
|
144
|
+
define_method("#{name}_element") do |*block_args, **block_options|
|
145
|
+
conv_args, conv_options = convert_arguments(args, options, block_args, block_options)
|
146
|
+
if conv_options.present?
|
147
|
+
capybara_context.find(*conv_args, **conv_options)
|
148
|
+
else
|
149
|
+
capybara_context.find(*conv_args)
|
150
|
+
end
|
117
151
|
end
|
118
152
|
private "#{name}_element"
|
119
153
|
end
|
120
154
|
|
121
|
-
def define_elements(name, args)
|
122
|
-
define_method("#{name}_elements") do |*block_args|
|
123
|
-
|
155
|
+
def define_elements(name, args, options)
|
156
|
+
define_method("#{name}_elements") do |*block_args, **block_options|
|
157
|
+
conv_args, conv_options = convert_arguments(args, options, block_args, block_options)
|
158
|
+
if conv_options.present?
|
159
|
+
capybara_context.all(*conv_args, **conv_options)
|
160
|
+
else
|
161
|
+
capybara_context.all(*conv_args)
|
162
|
+
end
|
124
163
|
end
|
125
164
|
private "#{name}_elements"
|
126
165
|
end
|
127
166
|
|
128
|
-
def define_wait_for_element(name, args)
|
129
|
-
define_method("wait_for_#{name}_element") do |*block_args|
|
130
|
-
|
167
|
+
def define_wait_for_element(name, args, options)
|
168
|
+
define_method("wait_for_#{name}_element") do |*block_args, **block_options|
|
169
|
+
conv_args, conv_options = convert_arguments(args, options, block_args, block_options)
|
170
|
+
if conv_options.present?
|
171
|
+
capybara_context.find(*conv_args, **conv_options)
|
172
|
+
else
|
173
|
+
capybara_context.find(*conv_args)
|
174
|
+
end
|
131
175
|
return nil
|
132
176
|
end
|
133
177
|
private "wait_for_#{name}_element"
|
134
178
|
end
|
135
179
|
|
136
|
-
def define_within_element(name, args)
|
137
|
-
define_method("within_#{name}_element") do |*block_args, &block|
|
138
|
-
|
180
|
+
def define_within_element(name, args, options)
|
181
|
+
define_method("within_#{name}_element") do |*block_args, **block_options, &block|
|
182
|
+
conv_args, conv_options = convert_arguments(args, options, block_args, block_options)
|
183
|
+
new_scope = if conv_options.present?
|
184
|
+
capybara_context.find(*conv_args, **conv_options)
|
185
|
+
else
|
186
|
+
capybara_context.find(*conv_args)
|
187
|
+
end
|
139
188
|
begin
|
140
189
|
capybara_scopes.push(new_scope)
|
141
190
|
block.call
|
@@ -145,15 +194,25 @@ module Howitzer
|
|
145
194
|
end
|
146
195
|
end
|
147
196
|
|
148
|
-
def define_has_element(name, args)
|
149
|
-
define_method("has_#{name}_element?") do |*block_args|
|
150
|
-
|
197
|
+
def define_has_element(name, args, options)
|
198
|
+
define_method("has_#{name}_element?") do |*block_args, **block_options|
|
199
|
+
conv_args, conv_options = convert_arguments(args, options, block_args, block_options)
|
200
|
+
if conv_options.present?
|
201
|
+
capybara_context.has_selector?(*conv_args, **conv_options)
|
202
|
+
else
|
203
|
+
capybara_context.has_selector?(*conv_args)
|
204
|
+
end
|
151
205
|
end
|
152
206
|
end
|
153
207
|
|
154
|
-
def define_has_no_element(name, args)
|
155
|
-
define_method("has_no_#{name}_element?") do |*block_args|
|
156
|
-
|
208
|
+
def define_has_no_element(name, args, options)
|
209
|
+
define_method("has_no_#{name}_element?") do |*block_args, **block_options|
|
210
|
+
conv_args, conv_options = convert_arguments(args, options, block_args, block_options)
|
211
|
+
if conv_options.present?
|
212
|
+
capybara_context.has_no_selector?(*conv_args, **conv_options)
|
213
|
+
else
|
214
|
+
capybara_context.has_no_selector?(*conv_args)
|
215
|
+
end
|
157
216
|
end
|
158
217
|
end
|
159
218
|
end
|
@@ -5,7 +5,7 @@ module Howitzer
|
|
5
5
|
module IframeDsl
|
6
6
|
include CapybaraContextHolder
|
7
7
|
|
8
|
-
def self.included(base)
|
8
|
+
def self.included(base) # :nodoc:
|
9
9
|
base.extend(ClassMethods)
|
10
10
|
end
|
11
11
|
|
@@ -26,7 +26,7 @@ module Howitzer
|
|
26
26
|
|
27
27
|
def convert_iframe_arguments(args, params)
|
28
28
|
new_args = args.deep_dup
|
29
|
-
hash = new_args.pop.merge(params) if new_args.last.is_a?(Hash)
|
29
|
+
hash = new_args.pop.transform_keys(&:to_sym).merge(params.transform_keys(&:to_sym)) if new_args.last.is_a?(Hash)
|
30
30
|
new_args << hash if hash.present?
|
31
31
|
new_args
|
32
32
|
end
|
data/lib/howitzer/web/page.rb
CHANGED
@@ -14,7 +14,7 @@ module Howitzer
|
|
14
14
|
module Web
|
15
15
|
# This class represents a single web page. This is a parent class for all web pages
|
16
16
|
class Page
|
17
|
-
UnknownPage = Class.new
|
17
|
+
UnknownPage = Class.new # :nodoc:
|
18
18
|
include Singleton
|
19
19
|
include CapybaraMethodsProxy
|
20
20
|
include ElementDsl
|
@@ -28,6 +28,7 @@ module Howitzer
|
|
28
28
|
# This Ruby callback makes all inherited classes as singleton classes.
|
29
29
|
|
30
30
|
def self.inherited(subclass)
|
31
|
+
super
|
31
32
|
subclass.class_eval { include Singleton }
|
32
33
|
end
|
33
34
|
|
@@ -40,7 +41,6 @@ module Howitzer
|
|
40
41
|
|
41
42
|
def self.open(validate: true, url_processor: nil, **params)
|
42
43
|
url = expanded_url(params, url_processor)
|
43
|
-
modify_user_agent if Howitzer.user_agent.present?
|
44
44
|
Howitzer::Log.info "Open #{name} page by '#{url}' url"
|
45
45
|
retryable(tries: 2, logger: Howitzer::Log, trace: true, on: Exception) do |retries|
|
46
46
|
Howitzer::Log.info 'Retry...' unless retries.zero?
|
@@ -151,22 +151,12 @@ module Howitzer
|
|
151
151
|
|
152
152
|
def incorrect_page_msg
|
153
153
|
"Current page: #{current_page}, expected: #{self}.\n" \
|
154
|
-
|
154
|
+
"\tCurrent url: #{current_url}\n\tCurrent title: #{instance.title}"
|
155
155
|
end
|
156
156
|
|
157
157
|
def ambiguous_page_msg(page_list)
|
158
158
|
"Current page matches more that one page class (#{page_list.join(', ')}).\n" \
|
159
|
-
|
160
|
-
end
|
161
|
-
|
162
|
-
def modify_user_agent
|
163
|
-
driver = Capybara.current_session.driver
|
164
|
-
case Howitzer.driver.to_sym
|
165
|
-
when CapybaraHelpers::POLTERGEIST
|
166
|
-
driver.add_headers('User-Agent' => Howitzer.user_agent)
|
167
|
-
when CapybaraHelpers::WEBKIT
|
168
|
-
driver.header('User-Agent', Howitzer.user_agent)
|
169
|
-
end
|
159
|
+
"\tCurrent url: #{current_url}\n\tCurrent title: #{instance.title}"
|
170
160
|
end
|
171
161
|
end
|
172
162
|
|
@@ -29,11 +29,15 @@ module Howitzer
|
|
29
29
|
# * `out` method extracts an instance variable from an original context if starts from @.
|
30
30
|
# Otherwise it executes a method from an original context
|
31
31
|
|
32
|
-
def method_missing(name, *args, &block)
|
32
|
+
def method_missing(name, *args, **options, &block)
|
33
33
|
return super if name =~ /\A(?:be|have)_/
|
34
|
-
return eval_in_out_context(*args, &block) if name == :out
|
34
|
+
return eval_in_out_context(*args, **options, &block) if name == :out
|
35
35
|
|
36
|
-
|
36
|
+
if options.present?
|
37
|
+
page_klass.given.send(name, *args, **options, &block)
|
38
|
+
else
|
39
|
+
page_klass.given.send(name, *args, &block)
|
40
|
+
end
|
37
41
|
end
|
38
42
|
|
39
43
|
# Makes proxied methods to be evaludated and returned as a proc
|
@@ -45,13 +49,17 @@ module Howitzer
|
|
45
49
|
|
46
50
|
private
|
47
51
|
|
48
|
-
def eval_in_out_context(*args, &block)
|
52
|
+
def eval_in_out_context(*args, **options, &block)
|
49
53
|
return nil if args.size.zero?
|
50
54
|
|
51
55
|
name = args.shift
|
52
56
|
return get_outer_instance_variable(name) if name.to_s.start_with?('@')
|
53
57
|
|
54
|
-
|
58
|
+
if options.present?
|
59
|
+
outer_context.send(name, *args, **options, &block)
|
60
|
+
else
|
61
|
+
outer_context.send(name, *args, &block)
|
62
|
+
end
|
55
63
|
end
|
56
64
|
|
57
65
|
def get_outer_instance_variable(name)
|
@@ -61,9 +69,10 @@ module Howitzer
|
|
61
69
|
attr_accessor :page_klass, :outer_context
|
62
70
|
end
|
63
71
|
|
64
|
-
def self.included(base)
|
72
|
+
def self.included(base) # :nodoc:
|
65
73
|
base.extend(ClassMethods)
|
66
74
|
end
|
75
|
+
|
67
76
|
# This module holds page dsl class methods
|
68
77
|
module ClassMethods
|
69
78
|
# Allows to execute page methods in context of the page.
|