howitzer 0.0.3 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +32 -0
- data/GETTING_STARTED.md +529 -0
- data/Gemfile +4 -2
- data/LICENSE +2 -2
- data/README.md +57 -13
- data/Rakefile +9 -2
- data/bin/howitzer +79 -31
- data/generators/base_generator.rb +87 -0
- data/generators/config/config_generator.rb +16 -20
- data/generators/config/templates/default.yml +26 -7
- data/generators/cucumber/cucumber_generator.rb +20 -26
- data/generators/{tasks → cucumber}/templates/cucumber.rake +0 -0
- data/generators/{config → cucumber}/templates/cucumber.yml +0 -0
- data/generators/emails/emails_generator.rb +11 -18
- data/generators/emails/templates/example_email.rb +1 -0
- data/generators/pages/pages_generator.rb +16 -18
- data/generators/pages/templates/example_menu.rb +1 -0
- data/generators/pages/templates/example_page.rb +1 -1
- data/generators/root/root_generator.rb +18 -20
- data/generators/root/templates/.gitignore +2 -1
- data/generators/root/templates/Gemfile +3 -2
- data/generators/root/templates/Rakefile +10 -0
- data/generators/root/templates/boot.rb +3 -9
- data/generators/rspec/rspec_generator.rb +23 -0
- data/generators/rspec/templates/example_spec.rb +7 -0
- data/generators/rspec/templates/rspec.rake +34 -0
- data/generators/rspec/templates/spec_helper.rb +56 -0
- data/generators/tasks/tasks_generator.rb +11 -17
- data/generators/tasks/templates/common.rake +15 -0
- data/howitzer.gemspec +13 -2
- data/lib/howitzer.rb +1 -0
- data/lib/howitzer/helpers.rb +87 -2
- data/lib/howitzer/init.rb +0 -1
- data/lib/howitzer/patches/rawler_patched.rb +86 -0
- data/lib/howitzer/settings.rb +27 -0
- data/lib/howitzer/utils.rb +3 -12
- data/lib/howitzer/utils/capybara_patched.rb +3 -2
- data/lib/howitzer/utils/capybara_settings.rb +158 -24
- data/lib/howitzer/utils/data_generator/data_storage.rb +35 -1
- data/lib/howitzer/utils/data_generator/gen.rb +45 -3
- data/lib/howitzer/utils/email/email.rb +44 -5
- data/lib/howitzer/utils/email/mail_client.rb +28 -22
- data/lib/howitzer/utils/email/mailgun_helper.rb +30 -4
- data/lib/howitzer/utils/locator_store.rb +111 -19
- data/lib/howitzer/utils/log.rb +137 -0
- data/lib/howitzer/utils/page_validator.rb +86 -0
- data/lib/howitzer/vendor/firebug-1.12.1-fx.xpi +0 -0
- data/lib/howitzer/vendor/firepath-0.9.7-fx.xpi +0 -0
- data/lib/howitzer/version.rb +2 -2
- data/lib/howitzer/web_page.rb +159 -19
- data/spec/active_resource.rb +0 -0
- data/spec/config/custom.yml +1 -0
- data/spec/config/default.yml +28 -0
- data/spec/spec_helper.rb +46 -1
- data/spec/support/boot_helper.rb +15 -0
- data/spec/support/generator_helper.rb +13 -0
- data/spec/support/logger_helper.rb +12 -0
- data/spec/unit/bin/howitzer_spec.rb +175 -0
- data/spec/unit/generators/generators_spec.rb +175 -0
- data/spec/unit/lib/capybara_settings_spec.rb +170 -0
- data/spec/unit/lib/helpers_spec.rb +619 -0
- data/spec/unit/lib/init_spec.rb +14 -0
- data/spec/unit/lib/settings_spec.rb +17 -0
- data/spec/unit/lib/utils/data_generator/data_storage_spec.rb +62 -0
- data/spec/unit/lib/utils/data_generator/gen_spec.rb +151 -0
- data/spec/unit/lib/utils/email/email_spec.rb +75 -0
- data/spec/unit/lib/utils/email/mail_client_spec.rb +115 -0
- data/spec/unit/lib/utils/email/mailgun_helper_spec.rb +95 -0
- data/spec/unit/lib/utils/locator_store_spec.rb +122 -0
- data/spec/unit/lib/utils/log_spec.rb +107 -0
- data/spec/unit/lib/utils/page_validator_spec.rb +142 -0
- data/spec/unit/lib/web_page_spec.rb +250 -0
- data/spec/unit/version_spec.rb +8 -0
- metadata +215 -15
- data/Gemfile.lock +0 -103
- data/History.md +0 -20
- data/lib/howitzer/utils/logger.rb +0 -108
- data/spec/howitzer/version_spec.rb +0 -8
@@ -1,19 +1,53 @@
|
|
1
1
|
module DataGenerator
|
2
2
|
|
3
|
+
##
|
4
|
+
#
|
5
|
+
# Data can be stored in memory using DataStorage
|
6
|
+
#
|
7
|
+
|
3
8
|
module DataStorage
|
4
9
|
@data ||= {}
|
5
10
|
|
6
11
|
class << self
|
12
|
+
|
13
|
+
##
|
14
|
+
#
|
15
|
+
# Saves data into memory. Marking by namespace and key
|
16
|
+
#
|
17
|
+
# *Parameters:*
|
18
|
+
# * +ns+ - Namespace
|
19
|
+
# * +key+ - Key that should be uniq in namespace
|
20
|
+
# * +value+ - Data value
|
21
|
+
#
|
22
|
+
|
23
|
+
|
7
24
|
def store(ns, key, value)
|
8
25
|
check_ns(ns)
|
9
26
|
@data[ns][key] = value
|
10
27
|
end
|
11
28
|
|
29
|
+
##
|
30
|
+
#
|
31
|
+
# Gets data from memory. Can get all namespace or single data value in namespace using key
|
32
|
+
#
|
33
|
+
# *Parameters:*
|
34
|
+
# * +ns+ - Namespace
|
35
|
+
# * +key+ - Key that isn't necessary required (default to: nil)
|
36
|
+
#
|
37
|
+
|
12
38
|
def extract(ns, key=nil)
|
13
39
|
check_ns(ns)
|
14
40
|
key ? @data[ns][key] : @data[ns]
|
15
41
|
end
|
16
42
|
|
43
|
+
##
|
44
|
+
#
|
45
|
+
# Deletes all records from namespace
|
46
|
+
#
|
47
|
+
# *Parameters:*
|
48
|
+
# * +ns+ - Namespace
|
49
|
+
#
|
50
|
+
|
17
51
|
def clear_ns(ns)
|
18
52
|
init_ns(ns)
|
19
53
|
end
|
@@ -38,4 +72,4 @@ module DataGenerator
|
|
38
72
|
|
39
73
|
end
|
40
74
|
end
|
41
|
-
end
|
75
|
+
end
|
@@ -1,11 +1,28 @@
|
|
1
1
|
module DataGenerator
|
2
2
|
module Gen
|
3
|
-
|
3
|
+
|
4
|
+
##
|
5
|
+
#
|
6
|
+
# This module generates uniq User object with uniq generated data.
|
7
|
+
# Examples:
|
4
8
|
# member = Gen::user #user.email: 'u<XXXX>@<settings.mail_pop3_domain>'
|
5
9
|
# member = Gen::user('user@test.com') #user.email: 'member@test.com'
|
6
|
-
# member = Gen::user(settings.def_test_user)
|
10
|
+
# member = Gen::user(settings.def_test_user) #user.email: settings.def_test_user
|
7
11
|
|
8
12
|
class << self
|
13
|
+
|
14
|
+
##
|
15
|
+
#
|
16
|
+
# Generates new User object with generated data.
|
17
|
+
#
|
18
|
+
# *Parameters:*
|
19
|
+
# * +params+ - Custom parameters
|
20
|
+
#
|
21
|
+
# *Returns:*
|
22
|
+
# * +user+ - New generated User object
|
23
|
+
#
|
24
|
+
|
25
|
+
|
9
26
|
def user(params={})
|
10
27
|
prefix = serial
|
11
28
|
default = {
|
@@ -18,6 +35,17 @@ module DataGenerator
|
|
18
35
|
User.new(default.merge(params))
|
19
36
|
end
|
20
37
|
|
38
|
+
##
|
39
|
+
#
|
40
|
+
# Gets User object by it's number
|
41
|
+
#
|
42
|
+
# *Parameters:*
|
43
|
+
# * +num+ - User number
|
44
|
+
#
|
45
|
+
# *Returns:*
|
46
|
+
# * +user+ - User object
|
47
|
+
#
|
48
|
+
|
21
49
|
def given_user_by_number(num)
|
22
50
|
data = DataStorage.extract('user', num.to_i)
|
23
51
|
unless data
|
@@ -27,11 +55,25 @@ module DataGenerator
|
|
27
55
|
data
|
28
56
|
end
|
29
57
|
|
58
|
+
##
|
59
|
+
#
|
60
|
+
# Generates uniq string
|
61
|
+
# @return [String] Generated string
|
62
|
+
#
|
63
|
+
# *Returns:*
|
64
|
+
# * +string+ - Generated string
|
65
|
+
#
|
66
|
+
|
30
67
|
def serial
|
31
68
|
a = [('a'..'z').to_a, (0..9).to_a].flatten.shuffle
|
32
69
|
"#{Time.now.utc.strftime("%j%H%M%S")}#{a[0..4].join}"
|
33
70
|
end
|
34
71
|
|
72
|
+
##
|
73
|
+
#
|
74
|
+
# Deletes mailboxes for all users that were generated before
|
75
|
+
#
|
76
|
+
|
35
77
|
def delete_all_mailboxes
|
36
78
|
DataStorage.extract('user').each_value do |user|
|
37
79
|
user.delete_mailbox
|
@@ -86,4 +128,4 @@ module DataGenerator
|
|
86
128
|
end
|
87
129
|
end
|
88
130
|
end
|
89
|
-
end
|
131
|
+
end
|
@@ -5,32 +5,71 @@ class Email
|
|
5
5
|
include RSpec::Matchers
|
6
6
|
attr_reader :recipient_address
|
7
7
|
|
8
|
+
##
|
9
|
+
#
|
10
|
+
# Creates new email with message
|
11
|
+
#
|
12
|
+
# *Parameters:*
|
13
|
+
# * +message+ - email message
|
14
|
+
#
|
15
|
+
|
8
16
|
def initialize(message)
|
9
|
-
message.subject.
|
17
|
+
expect(message.subject).to include(self.class::SUBJECT)
|
10
18
|
@recipient_address = ::Mail::Address.new(message.to.first)
|
11
19
|
@message = message
|
12
20
|
end
|
13
21
|
|
22
|
+
##
|
23
|
+
#
|
24
|
+
# Search mail by recepient
|
25
|
+
#
|
26
|
+
# *Parameters:*
|
27
|
+
# * +recepient+ - recepient's email address
|
28
|
+
#
|
29
|
+
|
14
30
|
def self.find_by_recipient(recipient)
|
15
31
|
find(recipient, self::SUBJECT)
|
16
32
|
end
|
17
33
|
|
34
|
+
##
|
35
|
+
#
|
36
|
+
# Search mail by recepient and subject.
|
37
|
+
#
|
38
|
+
# *Parameters:*
|
39
|
+
# * +recepient+ - recepient's email address
|
40
|
+
# * +subject+ - email subject
|
41
|
+
#
|
42
|
+
|
18
43
|
def self.find(recipient, subject)
|
19
|
-
|
20
|
-
|
44
|
+
messages = MailClient.by_email(recipient).find_mail do |mail|
|
45
|
+
/#{Regexp.escape(subject)}/ === mail.subject && mail.to == [recipient]
|
21
46
|
end
|
22
47
|
|
23
48
|
if messages.first.nil?
|
24
49
|
log.error "#{self} was not found (recipient: '#{recipient}')"
|
25
|
-
|
50
|
+
return # TODO check log.error raises error
|
26
51
|
end
|
27
52
|
new(messages.first)
|
28
53
|
end
|
29
54
|
|
55
|
+
##
|
56
|
+
#
|
57
|
+
# Returns plain text body of email message
|
58
|
+
#
|
59
|
+
|
30
60
|
def plain_text_body
|
31
61
|
get_mime_part(@message, 'text/plain').to_s
|
32
62
|
end
|
33
63
|
|
64
|
+
##
|
65
|
+
#
|
66
|
+
# Allows to get email MIME attachment
|
67
|
+
#
|
68
|
+
# *Parameters:*
|
69
|
+
# * +part+ - recepient's email address
|
70
|
+
# * +type+ - MIME message part
|
71
|
+
#
|
72
|
+
|
34
73
|
def get_mime_part(part, type)
|
35
74
|
return part.body if part["content-type"].to_s =~ %r!#{type}!
|
36
75
|
# Recurse the multi-parts
|
@@ -43,4 +82,4 @@ class Email
|
|
43
82
|
|
44
83
|
protected :get_mime_part
|
45
84
|
|
46
|
-
end
|
85
|
+
end
|
@@ -10,18 +10,41 @@ class MailClient
|
|
10
10
|
|
11
11
|
def self.default
|
12
12
|
log.info "Connect to default mailbox"
|
13
|
-
options =
|
14
|
-
@clients[options] =
|
13
|
+
options = merge_opts
|
14
|
+
@clients[options] = new unless @clients.has_key?(options)
|
15
15
|
@clients[options]
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.by_email(name)
|
19
19
|
log.info "Connect to '#{name}' mailbox"
|
20
|
-
options = self.merge_opts(:
|
21
|
-
@clients[options] =
|
20
|
+
options = self.merge_opts(pop3: { user_name: name }, smtp: {})
|
21
|
+
@clients[options] = new(options) unless @clients.has_key?(options)
|
22
22
|
@clients[options]
|
23
23
|
end
|
24
24
|
|
25
|
+
def self.merge_opts(opts={smtp: {}, pop3: {}})
|
26
|
+
def_smtp_opts = {
|
27
|
+
address: settings.mail_smtp_server,
|
28
|
+
port: settings.mail_smtp_port,
|
29
|
+
domain: settings.mail_smtp_domain,
|
30
|
+
user_name: settings.mail_smtp_user_name,
|
31
|
+
password: settings.mail_smtp_user_pass,
|
32
|
+
authentication: 'plain',
|
33
|
+
enable_starttls_auto: true
|
34
|
+
}
|
35
|
+
|
36
|
+
def_pop3_opts = {
|
37
|
+
address: settings.mail_pop3_server,
|
38
|
+
port: settings.mail_pop3_port,
|
39
|
+
user_name: settings.mail_pop3_user_name,
|
40
|
+
password: settings.mail_pop3_user_pass
|
41
|
+
}
|
42
|
+
{
|
43
|
+
smtp: def_smtp_opts.merge(opts[:smtp]),
|
44
|
+
pop3: def_pop3_opts.merge(opts[:pop3])
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
25
48
|
def find_mail(max_wait = settings.mail_pop3_timeout, keep_or_delete = :delete, &block)
|
26
49
|
messages = []
|
27
50
|
time_of_start = Time.now
|
@@ -98,7 +121,7 @@ class MailClient
|
|
98
121
|
|
99
122
|
private
|
100
123
|
def initialize(*arg)
|
101
|
-
@options =
|
124
|
+
@options = self.class.merge_opts(*arg)
|
102
125
|
Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
|
103
126
|
@old_ids = []
|
104
127
|
options = @options
|
@@ -106,21 +129,4 @@ class MailClient
|
|
106
129
|
@time_of_start = Time.now
|
107
130
|
end
|
108
131
|
|
109
|
-
def self.merge_opts(opts={:smtp => {}, :pop3 => {}})
|
110
|
-
def_smtp_opts = {:address => settings.mail_smtp_server,
|
111
|
-
:port => settings.mail_smtp_port,
|
112
|
-
:domain => settings.mail_smtp_domain,
|
113
|
-
:user_name => settings.mail_smtp_user_name,
|
114
|
-
:password => settings.mail_smtp_user_pass,
|
115
|
-
:authentication => 'plain',
|
116
|
-
:enable_starttls_auto => true}
|
117
|
-
|
118
|
-
def_pop3_opts = {:address => settings.mail_pop3_server,
|
119
|
-
:port => settings.mail_pop3_port,
|
120
|
-
:user_name => settings.mail_pop3_user_name,
|
121
|
-
:password => settings.mail_pop3_user_pass}
|
122
|
-
{:smtp => def_smtp_opts.merge(opts[:smtp]),
|
123
|
-
:pop3 => def_pop3_opts.merge(opts[:pop3])}
|
124
|
-
end
|
125
|
-
|
126
132
|
end
|
@@ -1,5 +1,16 @@
|
|
1
1
|
module MailgunHelper
|
2
2
|
|
3
|
+
##
|
4
|
+
#
|
5
|
+
# Creates new mailbox for given user_name
|
6
|
+
#
|
7
|
+
# *Parameters:*
|
8
|
+
# * +user_name+ - user name
|
9
|
+
# * +domain+ - domain (default to: settings.mail_pop3_domain )
|
10
|
+
# * +password+ - password (default to: settings.mail_pop3_user_pass )
|
11
|
+
#
|
12
|
+
|
13
|
+
|
3
14
|
def create_mailbox(user_name,
|
4
15
|
domain=settings.mail_pop3_domain,
|
5
16
|
password=settings.mail_pop3_user_pass)
|
@@ -9,6 +20,14 @@ module MailgunHelper
|
|
9
20
|
mbox
|
10
21
|
end
|
11
22
|
|
23
|
+
##
|
24
|
+
#
|
25
|
+
# Deletes given mailbox
|
26
|
+
#
|
27
|
+
# *Parameters:*
|
28
|
+
# * +mailbox+ - mailbox to delete
|
29
|
+
#
|
30
|
+
|
12
31
|
def delete_mailbox(mailbox)
|
13
32
|
log.info "Delete '#{mailbox.user}@#{mailbox.domain}' mailbox"
|
14
33
|
begin
|
@@ -18,11 +37,18 @@ module MailgunHelper
|
|
18
37
|
end
|
19
38
|
end
|
20
39
|
|
40
|
+
##
|
41
|
+
#
|
42
|
+
# Deletes all mailboxes except those in exceptions
|
43
|
+
#
|
44
|
+
# *Parameters:*
|
45
|
+
# * +exceptions+ - list of email addresses
|
46
|
+
#
|
47
|
+
|
21
48
|
def delete_all_mailboxes(*exceptions)
|
22
|
-
|
23
|
-
exceptions += %w"postmaster@#{settings.mail_smtp_domain}" #system and default mailbox
|
49
|
+
exceptions += ["postmaster@#{settings.mail_smtp_domain}"] #system and default mailbox
|
24
50
|
exceptions = exceptions.uniq
|
25
|
-
log.info "Delete all mailboxes
|
51
|
+
log.info "Delete all mailboxes except: #{exceptions.map(&:inspect).join(', ')}"
|
26
52
|
i = 0
|
27
53
|
Mailbox.find(:all).each do |m|
|
28
54
|
next if exceptions.include?("#{m.user}@#{m.domain}")
|
@@ -32,4 +58,4 @@ module MailgunHelper
|
|
32
58
|
|
33
59
|
log.info "Were deleted '#{i}' mailboxes"
|
34
60
|
end
|
35
|
-
end
|
61
|
+
end
|
@@ -18,52 +18,156 @@
|
|
18
18
|
|
19
19
|
|
20
20
|
module LocatorStore
|
21
|
+
BadLocatorParamsError = Class.new(StandardError)
|
22
|
+
LocatorNotDefinedError = Class.new(StandardError)
|
23
|
+
|
21
24
|
def self.included(base)
|
22
25
|
base.extend(ClassMethods)
|
23
26
|
end
|
24
27
|
|
25
28
|
module ClassMethods
|
29
|
+
LOCATOR_TYPES = [:base, :link, :field, :button]
|
26
30
|
class BadLocatorParamsError < StandardError; end
|
27
31
|
class LocatorNotSpecifiedError < StandardError; end
|
28
32
|
|
33
|
+
##
|
34
|
+
#
|
35
|
+
# Adds css or xpath locator into LocatorStore.
|
36
|
+
# Also locator can be set by lambda expression. For example: lambda{|name|{xpath: ".//a[@id='#{name}']"}}
|
37
|
+
#
|
38
|
+
# *Parameters:*
|
39
|
+
# * +name+ - Locator name
|
40
|
+
# * +params+ - String for css locator or hash with :xpath key and string value for xpath locator
|
41
|
+
#
|
42
|
+
|
29
43
|
def add_locator(name, params)
|
30
44
|
add_locator_by_type(:base, name, params)
|
31
45
|
end
|
32
46
|
|
47
|
+
##
|
48
|
+
#
|
49
|
+
# Adds locator for link into LocatorStore. Link can be found by: id, text
|
50
|
+
# Capybara methods that can work with this locator type are: click_link, find_link
|
51
|
+
#
|
52
|
+
# *Parameters:*
|
53
|
+
# * +name+ - Locator name
|
54
|
+
# * +params+ - ID or text of link
|
55
|
+
#
|
56
|
+
|
33
57
|
def add_link_locator(name, params)
|
34
58
|
add_locator_by_type(:link, name, params)
|
35
59
|
end
|
36
60
|
|
61
|
+
##
|
62
|
+
#
|
63
|
+
# Adds locator for field into LocatorStore. Field can be found by: name, id, text
|
64
|
+
# Capybara methods that can work with this locator type are: find_field, fill_in
|
65
|
+
#
|
66
|
+
# *Parameters:*
|
67
|
+
# * +name+ - Locator name
|
68
|
+
# * +params+ - Name, ID or text of field
|
69
|
+
#
|
70
|
+
|
37
71
|
def add_field_locator(name, params)
|
38
72
|
add_locator_by_type(:field, name, params)
|
39
73
|
end
|
40
74
|
|
75
|
+
##
|
76
|
+
#
|
77
|
+
# Add locator for button into LocatorStore. Button can be found by: id, name, value
|
78
|
+
# Capybara methods that can work with this locator type are: click_button, find_button
|
79
|
+
#
|
80
|
+
# *Parameters:*
|
81
|
+
# * +name+ - Locator name
|
82
|
+
# * +params+ - Name, ID or value
|
83
|
+
#
|
84
|
+
|
41
85
|
def add_button_locator(name, params)
|
42
86
|
add_locator_by_type(:button, name, params)
|
43
87
|
end
|
44
88
|
|
89
|
+
##
|
90
|
+
#
|
91
|
+
# Takes css or xpath locator from LocatorStore by name
|
92
|
+
#
|
93
|
+
# *Parameters:*
|
94
|
+
# * +name+ - Locator name
|
95
|
+
#
|
96
|
+
|
45
97
|
def locator(name)
|
46
98
|
locator_by_type(:base, name)
|
47
99
|
end
|
48
100
|
|
101
|
+
##
|
102
|
+
#
|
103
|
+
# Take link locator from LocatorStore by name
|
104
|
+
#
|
105
|
+
# *Parameters:*
|
106
|
+
# * +name+ - Locator name
|
107
|
+
#
|
108
|
+
|
49
109
|
def link_locator(name)
|
50
110
|
locator_by_type(:link, name)
|
51
111
|
end
|
52
112
|
|
113
|
+
##
|
114
|
+
#
|
115
|
+
# Take field locator from LocatorStore by name
|
116
|
+
#
|
117
|
+
# *Parameters:*
|
118
|
+
# * +name+ - Locator name
|
119
|
+
#
|
120
|
+
|
53
121
|
def field_locator(name)
|
54
122
|
locator_by_type(:field, name)
|
55
123
|
end
|
56
124
|
|
125
|
+
##
|
126
|
+
#
|
127
|
+
# Take button locator from LocatorStore be name
|
128
|
+
#
|
129
|
+
# *Parameters:*
|
130
|
+
# * +name+ - Locator name
|
131
|
+
#
|
132
|
+
|
57
133
|
def button_locator(name)
|
58
134
|
locator_by_type(:button, name)
|
59
135
|
end
|
60
136
|
|
137
|
+
##
|
138
|
+
#
|
139
|
+
# Get locator set by lambda.
|
140
|
+
# For example: find(apply(locator(:locator_name), 'register')).click
|
141
|
+
#
|
142
|
+
# *Parameters:*
|
143
|
+
# * +locator+ - Locator set with lambda expression
|
144
|
+
# * +values+ - Arguments that should be matched lambda expression params
|
145
|
+
#
|
146
|
+
|
61
147
|
def apply(locator, *values)
|
62
148
|
locator.call(*values).to_a.flatten
|
63
149
|
end
|
64
150
|
|
151
|
+
def find_element(name)
|
152
|
+
type, locator = find_locator(name)
|
153
|
+
if type == :base
|
154
|
+
send :find, locator
|
155
|
+
else
|
156
|
+
send "find_#{type}", locator
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
65
160
|
protected
|
66
161
|
|
162
|
+
def find_locator(name)
|
163
|
+
name = name.to_s.to_sym
|
164
|
+
LOCATOR_TYPES.each do|type|
|
165
|
+
return [type, locator_by_type(type, name)] if (@locators || {}).fetch(self.name, {}).fetch(type, {})[name]
|
166
|
+
end
|
167
|
+
raise(LocatorNotDefinedError, name)
|
168
|
+
end
|
169
|
+
|
170
|
+
# looks up locator in current and all super classes
|
67
171
|
def parent_locator(type, name)
|
68
172
|
if !@locators.nil? && @locators.key?(self.name) && @locators[self.name].key?(type) && @locators[self.name][type].key?(name)
|
69
173
|
@locators[self.name][type][name]
|
@@ -76,7 +180,7 @@ module LocatorStore
|
|
76
180
|
|
77
181
|
def locator_by_type(type, name)
|
78
182
|
locator = parent_locator(type, name)
|
79
|
-
raise(
|
183
|
+
raise(LocatorNotDefinedError, name) if locator.nil?
|
80
184
|
locator
|
81
185
|
end
|
82
186
|
|
@@ -96,23 +200,11 @@ module LocatorStore
|
|
96
200
|
end
|
97
201
|
end
|
98
202
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
self.class.link_locator(name)
|
105
|
-
end
|
106
|
-
|
107
|
-
def field_locator(name)
|
108
|
-
self.class.field_locator(name)
|
109
|
-
end
|
110
|
-
|
111
|
-
def button_locator(name)
|
112
|
-
self.class.button_locator(name)
|
203
|
+
#delegate class methods to instance
|
204
|
+
ClassMethods.public_instance_methods.each do |name|
|
205
|
+
define_method(name) do |*args|
|
206
|
+
self.class.send(name, *args)
|
207
|
+
end
|
113
208
|
end
|
114
209
|
|
115
|
-
|
116
|
-
self.class.apply(locator, *values)
|
117
|
-
end
|
118
|
-
end
|
210
|
+
end
|