zander 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3875d0299b3297f68eaa7e38a203019569f21a83
4
+ data.tar.gz: c0a8da31fe54b84197cc417c763e87fc8a99206c
5
+ SHA512:
6
+ metadata.gz: a532118b690fd416ad00181a5383ad1d2aea20b1cb547daedf52051ed7b7276fd8fda7e63b591c0bf4da3df8b98436a650e83cc78e55caae3ad0718f0ffd7918
7
+ data.tar.gz: 243f56c183f86eb198a7630964994530b86cb2df4e3eef1a688206630abd971b31ffdfa5e22e182f51fc434128cd4fb48d3f9f4c18f989981037100c21489265
data/.gitignore ADDED
@@ -0,0 +1,38 @@
1
+ share/html_v2.yaml
2
+ share/chromedriver
3
+
4
+ *.gem
5
+ *.rbc
6
+ /.config
7
+ /coverage/
8
+ /InstalledFiles
9
+ /pkg/
10
+ /spec/reports/
11
+ /test/tmp/
12
+ /test/version_tmp/
13
+ /tmp/
14
+
15
+ ## Specific to RubyMotion:
16
+ .dat*
17
+ .repl_history
18
+ build/
19
+
20
+ ## Documentation cache and generated files:
21
+ /.yardoc/
22
+ /_yardoc/
23
+ /doc/
24
+ /rdoc/
25
+
26
+ ## Environment normalisation:
27
+ /.bundle/
28
+ /lib/bundler/man/
29
+
30
+ # for a library or gem, you might want to ignore these files since the code is
31
+ # intended to run in multiple environments; otherwise, check them in:
32
+ # Gemfile.lock
33
+ # .ruby-version
34
+ # .ruby-gemset
35
+
36
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
37
+ .rvmrc
38
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gem 'selenium-webdriver', '~> 2.43.0'
3
+ gem 'json', '~> 1.8.1'
4
+ #gem 'prawn', '~> 1.3.0'
5
+ gem 'pdfkit', '~> 0.6.2'
6
+ gem 'yard', '~> 0.8.7.6'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Spencer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ Streamline Selenium WebDriver Testing with Zander
2
+ ---
data/bin/zander ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ #######################################################################################################
3
+ # This executable file is an example three ways to properly use 'zander'. #
4
+ # 1.) Demo version #
5
+ # Simply run this executable file. #
6
+ # $ ./zander #
7
+ # #
8
+ # The demo version will use the fiels provided in the gem's share directory. #
9
+ # share/sites.yaml #
10
+ # share/actions.yaml #
11
+ # #
12
+ # These files attempt to log on to a google account. #
13
+ # The user name and password are invalid, and the sign in will fail #
14
+ # #
15
+ # 2.) Custom files version #
16
+ # You must provid both the sites.yaml and actions.yaml #
17
+ # #
18
+ # #
19
+ # 3.) Specific version #
20
+ # This version allows you to provide an array of the websites you want exectued #
21
+ # [0] will only execute the actions for the first URL #
22
+ # [0,1] will execute the actions for the first two URLs, etc #
23
+ # #
24
+ # Note: In some cases full control over the driver and loggin is required #
25
+ # Include the Zander::Manual module which has the @@driver and @@log variables #
26
+ # overide the self.drive method and make sure to add a 'manual' call in your actions.yaml #
27
+ # a full example is shown at the bottom #
28
+ # #
29
+ #######################################################################################################
30
+ #require 'zander'
31
+ require '/Users/sc/projects/ruby/appeals/lib/zander'
32
+ #######################################################################################################
33
+ ### 1.) Demo - Uses share/sites.yaml and shre/actions.yaml ###
34
+ Zander.run ###
35
+ #######################################################################################################
36
+
37
+ #######################################################################################################
38
+ ### 2.) Custom files - Example specifying script fiels ###
39
+ #DIR = File.join((File.expand_path('../', File.expand_path(File.dirname(__FILE__)))), "/share/") ###
40
+ #Zander.run(sites: "#{DIR}sites.yaml", actions: "#{DIR}actions.yaml") ###
41
+ #######################################################################################################
42
+
43
+ #######################################################################################################
44
+ ### 3.) Specific - Eample specifing which URL entries to process ###
45
+ #Zander.run(sites: "#{DIR}sites.yaml", actions: "#{DIR}actions.yaml", steps: [0]) ###
46
+ #######################################################################################################
47
+
48
+ #######################################################################################################
49
+ ### Example file that uses the manual driving method ###
50
+ #######################################################################################################
51
+ # require 'zander' #
52
+ # include Zander::Manual #
53
+ # Zander::Manual.module_eval do #
54
+ # def self.drive #
55
+ # driver = @@driver #
56
+ # log = @@log #
57
+ # log.debug("I got the logger and the driver") #
58
+ # log.debug("current url: #{driver.current_url}") #
59
+ # end #
60
+ # end #
61
+ # Zander.run #
62
+ #######################################################################################################
data/lib/zander.rb ADDED
@@ -0,0 +1,59 @@
1
+ #####################################################################################################################
2
+ # ZANDER THE GREAT #
3
+ # ,__ #
4
+ # | `'. #
5
+ # __ |`-._/_.:---`-.._ #
6
+ # \='. _/..--'`__ `'-._ #
7
+ # \- '-.--"` === / o `', #
8
+ # )= ( .--_ | _.' #
9
+ # /_=.'-._ {=_-_ | .--`-. #
10
+ # /_.' `\`'-._ '-= \ _.' #
11
+ # ) _.-'`'-.. _..-'` #
12
+ # /_.' `/";';`| #
13
+ # \` .'/ #
14
+ # '--' #
15
+ # #
16
+ # Zander is a framerwork for facilitating automated Selenium webdriver testing #
17
+ # URLs and corrisponding log in credentials are defined in the share/sites.yaml #
18
+ # The actions to be taken and the element identifiers are defined in share/actions.yaml #
19
+ #####################################################################################################################
20
+ lib = File.expand_path('../../lib/', __FILE__)
21
+ $:.unshift lib unless $:.include?(lib)
22
+ # p $:.dup
23
+
24
+ module Zander
25
+ def self.run(sites: nil, actions: nil, steps: nil)
26
+
27
+ if steps == nil
28
+ steps = ARGV[0].split(',').map(&:to_i) unless ARGV[0] == nil
29
+ end
30
+
31
+ if (sites != nil && actions != nil)
32
+ zander = Sites.new(sites,steps)
33
+ zander.add_actions(actions)
34
+ else
35
+ zander = Sites.new(Util.get_path('share/sites.yaml'),steps)
36
+ zander.add_actions(Util.get_path('share/actions.yaml'))
37
+ end
38
+
39
+ zander.set_log_level Logger::DEBUG
40
+ zander.sites.each do |site|
41
+ site.drive
42
+ end
43
+
44
+ end
45
+ end
46
+ require 'zander/cmd_mapper'
47
+ require 'zander/sites'
48
+ require 'zander/action'
49
+ require 'zander/manual'
50
+ require 'zander/site'
51
+ require 'zander/util'
52
+ require 'zander/ht'
53
+
54
+ require 'selenium-webdriver'
55
+ require 'yaml'
56
+ require 'logger'
57
+
58
+
59
+
@@ -0,0 +1,225 @@
1
+ module Zander
2
+ class Action
3
+
4
+ def initialize(site, driver, log, hash)
5
+ @site = site
6
+ @log = log
7
+ @driver = driver
8
+ @private_variable = false
9
+ parse_before_action(hash)
10
+ parse_action_type(hash)
11
+ parse_after_action(hash)
12
+ @log.debug("Created #{self.class.name} #{self}")
13
+ end
14
+
15
+ def private_variable?
16
+ @private_variable
17
+ end
18
+
19
+ def parse_before_action(hash)
20
+ if hash.has_key?(:before_action)
21
+ @before_action = hash[:before_action]
22
+ end
23
+ end
24
+
25
+ def parse_after_action(hash)
26
+ if hash.has_key?(:after_action)
27
+ @after_action = hash[:after_action]
28
+ end
29
+ end
30
+
31
+ def parse_action_type(hash)
32
+ if hash.has_key? :action_type
33
+ @action_type = hash[:action_type]
34
+ parse_type(hash)
35
+ end
36
+ end
37
+
38
+ def parse_type(hash)
39
+ case @action_type
40
+ when 'click_element','print_element','switch_to_iframe'
41
+ set_identifier(hash)
42
+ when 'input_variable'
43
+ set_identifier(hash)
44
+ set_variable(hash)
45
+ when 'input_data'
46
+ set_identifier(hash)
47
+ set_data(hash)
48
+ when 'done','switch_to_new_window'
49
+ else
50
+ @log.error("#{__method__} can't handle action_type #{@action_type} for #{self}")
51
+ end
52
+ end
53
+
54
+ def set_identifier(hash)
55
+ if hash.has_key? :identifier
56
+ identifier = hash[:identifier]
57
+ @finder_key = identifier.keys[0]
58
+ @finder_value = identifier.values[0]
59
+ end
60
+ end
61
+
62
+ def set_variable(hash)
63
+ if hash.has_key? :variable
64
+ @private_variable = true if hash[:variable] == "password"
65
+ @variable = @site.instance_variable_get("@#{hash[:variable]}".to_sym)
66
+ end
67
+ end
68
+
69
+ def set_data(hash)
70
+ if hash.has_key? :data
71
+ @data = hash[:data]
72
+ end
73
+ end
74
+
75
+ def drive
76
+ element = get_element
77
+ do_action(element)
78
+ sleep(1)
79
+ end
80
+
81
+ def get_element
82
+ case @action_type
83
+ when 'click_element', 'input_variable', 'print_element','switch_to_iframe', 'input_data'
84
+ get_element_from_finders
85
+ when 'done','switch_to_new_window'
86
+ else
87
+ @log.error("Can't handle action_type #{@action_type} for #{self}")
88
+ end
89
+ end
90
+
91
+ def get_element_from_finders
92
+ if @finder_key != nil
93
+ @log.debug("Find element #{@finder_key}='#{@finder_value}'")
94
+ case @finder_key
95
+ when :id,:name,:xpath
96
+ element = @driver.find_element(@finder_key => @finder_value)
97
+ when :css
98
+ when :class
99
+ # could be multiple // might need to add a n: 0
100
+ element = @driver.find_element(@finder_key => @finder_value)
101
+ when :class_name
102
+ when :link
103
+ when :link_text
104
+ when :partial_link_text
105
+ when :tag_name
106
+ else
107
+ @log.error("#{__method__} invalid finder_key, must be a Selenium::WebDriver::SearchContext::FINDERS:")
108
+ @log.error(Selenium::WebDriver::SearchContext::FINDERS.keys)
109
+ end
110
+ else
111
+ @log.error("#{__method__} tried to locate element, but @finder_key == nil")
112
+ end
113
+ element
114
+ end
115
+
116
+ def get_elements_from_finders
117
+ if @finder_key != nil
118
+ @log.debug("Find elements #{@finder_key}='#{@finder_value}'")
119
+ case @finder_key
120
+ when :id
121
+ element = @driver.find_elements(@finder_key => @finder_value)
122
+ when :xpath
123
+ element = @driver.find_elements(:xpath, identifier[:xpath])
124
+ when :css
125
+ when :class
126
+ when :class_name
127
+ when :name
128
+ when :link
129
+ when :link_text
130
+ when :partial_link_text
131
+ when :tag_name
132
+ else
133
+ @log.error("#{__method__} invalid finder_key, must be a Selenium::WebDriver::SearchContext::FINDERS:")
134
+ @log.error(Selenium::WebDriver::SearchContext::FINDERS.keys)
135
+ end
136
+ else
137
+ @log.error("#{__method__} tried to locate element, but @finder_key == nil")
138
+ end
139
+ element
140
+ end
141
+
142
+ def do_action(element)
143
+ @log.debug("try #{@action_type} #{@finder_key}='#{@finder_value}'")
144
+ case @action_type
145
+ when 'click_element'
146
+ element.click
147
+ when 'input_variable'
148
+ @log.info("Send '#{masked_variable}' to #{@finder_key}='#{@finder_value}' element")
149
+ element.clear
150
+ element.send_keys @variable
151
+ when 'print_element'
152
+ @log.info("text: #{element.text}
153
+ \t\ttag_name: #{element.tag_name}
154
+ \t\tlocation: (#{element.location.x},#{element.location.y})")
155
+ when 'input_data'
156
+ @log.info("Send '#{@data}' to #{@finder_key}='#{@finder_value}' element")
157
+ element.clear
158
+ element.send_keys @data
159
+ when 'switch_to_iframe'
160
+ @log.error("Can't locate iframe with #{@finder_key}='#{@finder_value}'. iframe can only be located via 'id'") unless @finder_key == :id
161
+ @driver.switch_to.frame(@finder_value)
162
+ sleep(3)
163
+ when 'switch_to_new_window'
164
+ @log.debug("'main_window' saved")
165
+ main_window = @driver.window_handle
166
+ new_window = nil
167
+ @driver.window_handles.each do |window|
168
+ if main_window != nil && main_window != window
169
+ new_window = window
170
+ end
171
+ end
172
+ @log.error("Couldn't find new window") if new_window == nil
173
+ @driver.switch_to.window(new_window)
174
+ @log.debug("Switched to new window #{driver.current_url}")
175
+ close_other_windows
176
+ when 'done'
177
+ close_other_windows
178
+ @driver.quit if @site.last?
179
+ else
180
+ @log.error("Could not preform action #{@action_type} on #{@finder_key}='#{@finder_value}' element")
181
+ end
182
+ @log.info("#{@action_type} #{@finder_key}='#{@finder_value}'")
183
+ end
184
+
185
+ def close_other_windows
186
+ main_window = @driver.window_handle
187
+ @driver.window_handles.each do |other_window|
188
+ if main_window != nil && main_window != other_window
189
+ @driver.switch_to.window(other_window)
190
+ url = @driver.current_url
191
+ @driver.close
192
+ @log.debug("Closed window '#{url}'")
193
+ end
194
+ end
195
+ @driver.switch_to.window(main_window)
196
+ end
197
+
198
+ def masked_variable
199
+ if private_variable?
200
+ clear = 3 #keep last 3 in clear text
201
+ masked = @variable[0];
202
+ (@variable.length-(clear+1)).times do
203
+ masked << '*'
204
+ end
205
+ masked << @variable[(@variable.length-clear)...@variable.length]
206
+ else
207
+ @variable
208
+ end
209
+ end
210
+
211
+ def inspect
212
+ to_s
213
+ end
214
+
215
+ def to_s
216
+ "<#{self.class.name}:0x#{'%x'%(self.object_id<<1)} @site=<Site:0x#{'%x'%(@site.object_id<<1)} ...> @action_type=#{@action_type} >"
217
+ end
218
+
219
+ private :to_s, :masked_variable, :close_other_windows
220
+ private :do_action, :get_element_from_finders, :get_elements_from_finders
221
+ private :get_element, :set_data, :set_variable, :set_identifier
222
+ private :parse_after_action, :parse_action_type, :parse_before_action
223
+ private :private_variable?
224
+ end
225
+ end
@@ -0,0 +1,21 @@
1
+ module Zander
2
+ module CommandMapper
3
+ def self.map(site, driver, log, cmd)
4
+ @site = site
5
+ @driver = driver
6
+ @log = log
7
+ @cmd = cmd
8
+ if cmd.is_a?(Hash)
9
+ if cmd.has_key? :action
10
+ Action.new(@site, @driver, @log, @cmd)
11
+ elsif cmd.has_key? :manual
12
+ Manual.set(@driver, @log)
13
+ Manual.drive
14
+ Manual.destroy
15
+ else
16
+ @log.error("Can't mapp comand for #{cmd.inspect}")
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/zander/ht.rb ADDED
@@ -0,0 +1,20 @@
1
+ # Hash Tools
2
+ class Hash
3
+ def change_keys(hash)
4
+ hash.each do |key,value|
5
+ if !key.is_a?(Hash) && !value.is_a?(Hash)
6
+ hash = hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
7
+ else
8
+ hash.map{ |k,v| hash[k] = change_keys(v) if v.is_a?(Hash) }
9
+ end
10
+ end
11
+ hash = hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
12
+ end
13
+
14
+
15
+ def keys_to_sym
16
+ change_keys(self)
17
+ end
18
+
19
+ private :change_keys
20
+ end
@@ -0,0 +1,17 @@
1
+ module Zander
2
+ module Manual
3
+ def self.set(driver, log)
4
+ @@driver = driver
5
+ @@log = log
6
+ end
7
+
8
+ def self.drive
9
+ ## empty method to implement
10
+ end
11
+
12
+ def self.destroy
13
+ @@driver = nil
14
+ @@log = nil
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,90 @@
1
+ module Zander
2
+ class Site
3
+
4
+ def initialize(parent:, hash:, driver:, log:)
5
+ @actions = Array.new
6
+ @parent = parent unless parent == nil
7
+ @log = log unless log == nil
8
+ @driver = driver unless driver == nil
9
+ create_attr_accessor(hash)
10
+ @log.debug("Created #{self}")
11
+ end
12
+
13
+ def get_variables
14
+ Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
15
+ end
16
+
17
+ # Map each hash in actions array with CommandMapper.
18
+ # If the result is an Action object, add it to the acctions array
19
+ def add_actions(actions)
20
+ actions.each do |action|
21
+ # convert keys in action hash to symbols
22
+ puts "Action Hash::: #{action}"
23
+ action = action.keys_to_sym
24
+ @log.debug("Create action #{action}")
25
+ obj = CommandMapper.map(self, @driver, @log, action)
26
+ @actions.push(obj) if obj.is_a?(Action)
27
+ end
28
+ end
29
+
30
+ # Is this instance the last Site object defined in share/sites.yaml
31
+ def last?
32
+ @url != nil && @parent.sites.last.respond_to?(:url) && @parent.sites.last.url == @url
33
+ end
34
+
35
+ def drive()
36
+ @driver.navigate.to self.url
37
+ @log.info("Opened #{@driver.current_url}")
38
+ @actions.each do |action|
39
+ action.drive
40
+ end
41
+ end
42
+
43
+ # Creates instance variables for each key value in a given hash
44
+ # { url => 'www.google.com', user_name => 'coolUser', password => 'secretPassword' }
45
+ # would create the following instance variables
46
+ # @url = 'www.google.com'
47
+ # @user_name = 'coolUser'
48
+ # @password = 'secretPassword'
49
+ def create_attr_accessor(hash)
50
+ hash.each do |key,value|
51
+ value = value.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} if value.is_a?(Hash)
52
+ instance_variable_set("@#{key}", value)
53
+ self.class.__send__(:attr_accessor, "#{key}")
54
+ self.__send__("#{key}=", value)
55
+ end
56
+ end
57
+
58
+ # Helper method for to_s
59
+ # returns a pretty string of all the actions
60
+ def get_vars
61
+ vars = ""
62
+ vh = Hash[self.instance_variables.map {|name|[name, instance_variable_get(name)]}]
63
+ vh.each_with_index do |(key,value), index|
64
+ if key.to_s == "@parent"
65
+ vars << @parent.get_abbr_to_s
66
+ elsif key.to_s == "@actions"
67
+ @actions.each do |action|
68
+ vars << action.to_s
69
+ end
70
+ elsif index == vh.size - 1
71
+ vars << "#{key}=\"#{value}\""
72
+ else
73
+ "#{key}=\"#{value}\", "
74
+ end
75
+ end
76
+ vars
77
+ end
78
+
79
+ def inspect
80
+ to_s
81
+ end
82
+
83
+ def to_s
84
+ "<#{self.class.name}:0x#{'%x'%(self.object_id<<1)} #{get_vars}"
85
+ end
86
+
87
+ private :to_s, :get_vars, :create_attr_accessor, :get_variables
88
+
89
+ end
90
+ end
@@ -0,0 +1,88 @@
1
+ module Zander
2
+ class Sites
3
+ IMPLICIT_WAIT = 10
4
+ YAML_URL = 'URL'
5
+ YAML_ACTIONS = 'ACTIONS'
6
+ LOG_FILE = STDOUT # 'log.txt'
7
+
8
+ attr_reader :sites
9
+
10
+ def initialize(yaml_file, steps = nil)
11
+ @sites_yaml_file = yaml_file
12
+ @log = Logger.new(LOG_FILE,10,1024000)
13
+ @log.level = Logger::DEBUG
14
+ @sites = Array.new
15
+ ### FIREFOX PROFILE
16
+ profile = Selenium::WebDriver::Firefox::Profile.new
17
+ profile['browser.download.dir'] = '/Users/sc/Desktop/appeals/HCFA_AND_POTF'
18
+ profile['browser.download.folderList'] = 2
19
+ profile['browser.helperApps.neverAsk.saveToDisk'] = "application/pdf"
20
+ profile['browser.download.alertOnEXEOpen'] = false
21
+ profile['browser.download.manager.showWhenStarting'] = false
22
+ profile['browser.download.manager.focusWhenStarting'] = false
23
+ profile['browser.helperApps.alwaysAsk.force'] = false
24
+ profile['browser.download.manager.alertOnEXEOpen'] = false
25
+ profile['browser.download.manager.closeWhenDone'] = false
26
+ profile['browser.download.manager.showAlertOnComplete'] = false
27
+ profile['browser.download.manager.useWindow'] = false
28
+ profile['browser.download.manager.showWhenStarting'] = false
29
+ profile['services.sync.prefs.sync.browser.download.manager.showWhenStarting'] = false
30
+ profile['pdfjs.disabled'] = true
31
+ ## END FIREFOX PROFILE
32
+ @driver = Selenium::WebDriver.for :firefox, :profile => profile
33
+ @driver.manage.timeouts.implicit_wait = IMPLICIT_WAIT
34
+ @log.debug("Selenium timeouts set to #{IMPLICIT_WAIT} seconds")
35
+ yaml = YAML::load(File.read(@sites_yaml_file))
36
+ if yaml.has_key? 'WEBSITES'
37
+ yaml['WEBSITES'].each_with_index do |site, index|
38
+ if steps == nil
39
+ @log.debug("Create Site #{site}")
40
+ @sites.push(Site.new(parent: self, hash: site, driver: @driver, log: @log))
41
+ else
42
+ if steps.include?(index)
43
+ @log.debug("Create Site #{site}")
44
+ @sites.push(Site.new(parent: self, hash: site, driver: @driver, log: @log))
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
52
+ def set_log_level(level)
53
+ @log.level = level
54
+ end
55
+
56
+ def get_site(url)
57
+ @sites.each do |site|
58
+ return site if site.url == url
59
+ end
60
+ nil
61
+ end
62
+
63
+ def get_abbr_to_s
64
+ "<#{self.class.name}:0x#{'%x'%(self.object_id<<1)} ...>"
65
+ end
66
+
67
+ def add_actions(yaml_file)
68
+ yaml = YAML::load(File.read(yaml_file))
69
+ if yaml.has_key? 'WEBSITES'
70
+ yaml['WEBSITES'].each do |website|
71
+ if website.has_key?(YAML_URL) && website.has_key?(YAML_ACTIONS)
72
+ site = self.get_site(website[YAML_URL])
73
+ if site != nil
74
+ @log.debug("Add #{website[YAML_ACTIONS]}")
75
+ site.add_actions(website[YAML_ACTIONS])
76
+ else
77
+ @log.error("Error:: '#{website[YAML_URL]}' in #{yaml_file} was not in #{@sites_yaml_file}")
78
+ end
79
+ else
80
+ @log.error("#{yaml_file} doesn't contain a #{YAML_URL} array")
81
+ end
82
+ end
83
+ else
84
+ @log.error("#{yaml_file} doesn't contain a WEBSITES array")
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,8 @@
1
+ # Utility helpers
2
+ module Zander
3
+ module Util
4
+ def self.get_path(file_name)
5
+ File.join((File.expand_path('../../', File.expand_path(File.dirname(__FILE__)))), file_name)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Zander
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,56 @@
1
+ ##
2
+ # Attribues is a hash of hashes the first hash will always be the way to identify an
3
+ # html tag ie (id: user_id or class: members) The action hash will consist of a simple action like click
4
+ # or could contain a complex action like input which will contain a field that mapps to a website object
5
+ #
6
+ # Gmail login example:
7
+ #WEBSTIES:
8
+ # - URL: https://accounts.google.com
9
+ # id: Email
10
+ # action:
11
+ # - variable: user_name
12
+ # id: Passwd
13
+ # action:
14
+ # - variable: password
15
+ # id: signIn
16
+ # action: click
17
+ # This yaml file would know that for https://accounts.google.com it should find the html attribute
18
+ # <input id="Email" name="Email" placeholder="Email" value="" spellcheck="false" class="" type="email">
19
+ # and insert the WebSite#user_name value
20
+ #
21
+ ##
22
+ WEBSITES:
23
+ - URL: https://www.google.com/
24
+ ACTIONS:
25
+ - action:
26
+ action_type: click_element
27
+ identifier:
28
+ id: gb_70
29
+ - action:
30
+ action_type: print_element
31
+ identifier:
32
+ class: tagline
33
+ - action:
34
+ action_type: input_variable
35
+ identifier:
36
+ id: Email
37
+ variable: user_name
38
+ - action:
39
+ action_type: input_variable
40
+ identifier:
41
+ id: Passwd
42
+ variable: password
43
+ - action:
44
+ action_type: click_element
45
+ identifier:
46
+ id: signIn
47
+ - manual:
48
+ - action:
49
+ action_type: done
50
+ # - URL:
51
+ # ATTRIBUTES:
52
+ # - identifier:
53
+ # id:
54
+ # action:
55
+ # - identifier:
56
+ # action: done
data/share/sites.yaml ADDED
@@ -0,0 +1,17 @@
1
+ #############################################
2
+ # Browsie can handle multiple arguements all
3
+ # that is required is that each email have
4
+ # corresponding password, and that each
5
+ # argument have a space followed by a '-'
6
+ # followed by another space, then the argument
7
+ #
8
+ # If you don't have one or both of these accounts
9
+ # delete out the keywords and arguments alltogether.
10
+ #############################################
11
+ WEBSITES:
12
+ - url: https://www.google.com/
13
+ user_name: "Replace this with your username"
14
+ password: "Replace this with your password"
15
+ # - url:
16
+ # user_name:
17
+ # password:
data/zander.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ lib = File.expand_path('../lib/', __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'zander/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'zander'
8
+ s.version = Zander::VERSION
9
+ s.date = '2014-11-13'
10
+ s.licenses = ['MIT']
11
+ s.summary = "Simple Web Automation"
12
+ s.description = "Zabner will help automate web testing using Selenium::WebDriver"
13
+ s.authors = ["Spencer Carlson"]
14
+ s.email = 'spencerdcarlson@gmail.com'
15
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ s.executables = %w(zander)
17
+ s.homepage = ''
18
+ s.require_paths = %w(lib)
19
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zander
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Spencer Carlson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Zabner will help automate web testing using Selenium::WebDriver
14
+ email: spencerdcarlson@gmail.com
15
+ executables:
16
+ - zander
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - Gemfile
22
+ - LICENSE
23
+ - README.md
24
+ - bin/zander
25
+ - lib/zander.rb
26
+ - lib/zander/action.rb
27
+ - lib/zander/cmd_mapper.rb
28
+ - lib/zander/ht.rb
29
+ - lib/zander/manual.rb
30
+ - lib/zander/site.rb
31
+ - lib/zander/sites.rb
32
+ - lib/zander/util.rb
33
+ - lib/zander/version.rb
34
+ - share/actions.yaml
35
+ - share/sites.yaml
36
+ - zander.gemspec
37
+ homepage: ''
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.2.2
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Simple Web Automation
61
+ test_files: []
62
+ has_rdoc: