shiken 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5edfc3ceb874cd976dd729485e38e8752cdc693a
4
+ data.tar.gz: ec9dd9bfc1143a913e956c3d96b50ad659db0468
5
+ SHA512:
6
+ metadata.gz: 21d62b4814a02148e10f94a1a64be9cc993af62a04c4402d4202a4fb51dad74ef8d55c9271e6a03ae75e865682c96bcfd7d005f42a84218f5d1bf5e622d3b9cb
7
+ data.tar.gz: 90b5dc74cff9bead2d8461e0e48a0005da7e43981b2ae426b7a28bc95a73326ac7b58ec7b91174f95c71cc5cc3d47a8790edbc0799b7567bad98c6699f94f74c
@@ -0,0 +1,266 @@
1
+ require 'selenium-webdriver'
2
+ require 'shiken/trace'
3
+ require 'uri'
4
+
5
+ module SK::Browser
6
+
7
+ extend self
8
+
9
+ ### local utilities
10
+
11
+ def pause(secs,text="")
12
+ trace("pause #{secs} seconds #{text}")
13
+ sleep secs
14
+ end
15
+ def trace(s)
16
+ SK::Trace.trace(s)
17
+ end
18
+ def error(s)
19
+ SK::Trace.error(s)
20
+ end
21
+ def warn(s)
22
+ SK::Trace.notice(s)
23
+ end
24
+
25
+ ###### main stuff #########
26
+
27
+ def goto(site,page='')
28
+ gotourl("https://#{site}/#{page}")
29
+ end
30
+ def gotox(site,page='')
31
+ gotourl("http://#{site}/#{page}")
32
+ end
33
+ def gotourl(url,seconds=1)
34
+ uri = URI.escape(url)
35
+ puts("go to #{uri}")
36
+ rescue_exceptions { SK::driver.get uri }
37
+ sleep seconds
38
+ end
39
+
40
+ def option(dd)
41
+ warn "browser.option is depricated. use SK::Dropdown instead"
42
+ Selenium::WebDriver::Support::Select.new(dd)
43
+ end
44
+
45
+ def select(locator,value)
46
+ dropdown(locator,"option",value)
47
+ end
48
+
49
+ def dropdown(locator,tagname,list_option)
50
+ warn "browser.dropdown is depricated. use SK::Dropdown instead. locator=#{locator}"
51
+ # actually returns the option object for the dropdown
52
+ # so the calling code can chain a select by method
53
+ # option(find({name: name}))
54
+ select_box = find(locator)
55
+ # select_box = $driver.find_element(locator)
56
+ _dropdown_el(select_box,tagname,list_option)
57
+ end
58
+ def _dropdown_el(select_box,tagname,list_option)
59
+ # trace "dropdown el... select_box=#{select_box}"
60
+ # trace "dropdown el... tagname=#{tagname} option=#{list_option}"
61
+
62
+ # actually returns the option object for the dropdown
63
+ # so the calling code can chain a select by method
64
+ # option(find({name: name}))
65
+ options = select_box.find_elements(:tag_name => "#{tagname}")
66
+
67
+ options.each do |option_field|
68
+ # trace "looking at #{option_field.text}"
69
+ if option_field.text == "#{list_option}"
70
+ option_field.click
71
+ break
72
+ end
73
+ end
74
+ end
75
+
76
+ def search(base_locator,target_locator,value,attr='text')
77
+ # search within the locator element for all matching tags (by name)
78
+ # return that element that has the attribute of text that matches
79
+ # the text_value passed
80
+ element = find(base_locator)
81
+ unless element # was found
82
+ error "wt search: element not found. locator = #{base_locator}"
83
+ return false
84
+ end
85
+ elements = element.find_elements(target_locator)
86
+ elements.each do |el|
87
+ el_attr = _get_attribute(el,attr)
88
+ # trace "wt search at #{el_attr} for #{value}"
89
+ return el if el_attr == "#{value}"
90
+ end
91
+ return false
92
+ end
93
+
94
+ def _get_attribute(el,attr)
95
+ attr == 'text' ? el.text : el.attribute(attr)
96
+ end
97
+
98
+ def radio(locator)
99
+ warn "browser.radio is depricated. use SK::RadioSet instead. locator=#{locator}"
100
+ self.click(locator,0)
101
+ end
102
+
103
+ def set(locator,value)
104
+ # set now accepts a single or an
105
+ # array of locators, by using newfind
106
+ el = find(locator)
107
+ error "cannot set #{locator}" unless el
108
+ _set_el(el,value) if el
109
+ end
110
+ def _set_el(el,value)
111
+ el.clear
112
+ el.send_keys(value)
113
+ end
114
+
115
+ def submit(name,secs=1)
116
+ click(name: name)
117
+ sleep secs
118
+ end
119
+
120
+ def find(param)
121
+ # find accepts a single value or array
122
+ # of locators to find an element. the array
123
+ # is meant to be a this under this structure
124
+ if param.kind_of?(Array)
125
+ base = driver
126
+ param.reverse.each do |loc|
127
+ base = _find_inside(loc,base)
128
+ end
129
+ return base
130
+ else
131
+ # not an array, a single
132
+ _find_inside(param,driver)
133
+ end
134
+ end
135
+
136
+ def _find_inside(locator, base)
137
+ # trace "find inside. locator=#{locator} base=#{base}"
138
+ # find an element by locator inside another element (base)
139
+ case
140
+ when locator.has_key?(:value)
141
+ # trace "... locate by value: #{locator[:value]}}"
142
+ find_input(:value,locator[:value])
143
+ when locator.has_key?(:type)
144
+ # trace "... locate by type: #{locator[:type]}"
145
+ find_input(:type,locator[:type])
146
+ else
147
+ # a standard selenium locator so just use it
148
+ rescue_exceptions { base.find_element(locator) }
149
+ end
150
+ end
151
+
152
+ def find_input(key,type)
153
+ # selenium does not support a locator search by type
154
+ # so we need a specialized function to find the element
155
+ elements = all({tag_name: 'input'})
156
+ elements.find do |e|
157
+ # trace "> #{e.attribute(key)} :: #{type}"
158
+ e.attribute(key) == type
159
+ end
160
+ end
161
+
162
+ def all(locator)
163
+ rescue_exceptions { driver.find_elements(locator) }
164
+ end
165
+
166
+ def match(text,locator)
167
+ elements = all(locator)
168
+ # trace("searching #{elements.length} links...")
169
+ elements.find{ |e| e.text.include? text }
170
+ end
171
+
172
+ def count_refs(ref, locator)
173
+ elements = all(locator)
174
+ # trace("count from #{elements.length} links...")
175
+ elements.count{ |e| e.attribute('href').include? ref }
176
+ end
177
+
178
+ def has_content?(content)
179
+ # puts trace("has content? #{content}")
180
+ return self.source.include? content
181
+ end
182
+
183
+ def has_el?(locator)
184
+ find(locator)
185
+ # rescue_exceptions { driver.find_element(locator) }
186
+ end
187
+
188
+ def has_text?(locator,text)
189
+ find(locator).text == text
190
+ end
191
+
192
+ def get_rows(locator,less_row)
193
+ rest = less_row.to_i
194
+ #table = rescue_exceptions { driver.find_elements(table_count) }
195
+ table = all(locator)
196
+ return table.count-rest
197
+ end
198
+
199
+ def get_text(locator)
200
+ find(locator).text
201
+ # return rescue_exceptions { driver.find_element(locator).text }
202
+ end
203
+
204
+ def get_value(locator)
205
+ find(locator).attribute('value')
206
+ end
207
+
208
+ ### Actions ####
209
+
210
+ def click(locator,pause=0)
211
+ SK::Trace.trace("*** click is depricated")
212
+ el = find(locator)
213
+ _click_el(el,pause) if el
214
+ end
215
+
216
+ def _click_el(el,extra)
217
+ SK::Trace.trace("*** click_el")
218
+ rescue_exceptions { el.click }
219
+ sleep 1+extra
220
+ self
221
+ end
222
+
223
+ ### Key Core Operations ###
224
+
225
+ def rescue_exceptions
226
+ # we do not want our tests to fail because selenium throws an error
227
+ # instead we want to explicitly test using "expects" in the cases
228
+ begin
229
+ yield
230
+ rescue Selenium::WebDriver::Error::NoSuchElementError
231
+ warn "Element does not exist."
232
+ false
233
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
234
+ warn "Element is stale."
235
+ false
236
+ rescue Selenium::WebDriver::Error::ElementNotVisibleError
237
+ warn "Element is not visible."
238
+ false
239
+ rescue Selenium::WebDriver::Error::WebDriverError => e
240
+ error "Webdriver Error. #{e}"
241
+ false
242
+ rescue Net::ReadTimeout
243
+ error "Network Timeout - no response."
244
+ false
245
+ rescue IOError
246
+ error "IOError"
247
+ false
248
+ end
249
+ end
250
+
251
+ ### Simple Accessors ####
252
+
253
+ def driver
254
+ SK::driver
255
+ end
256
+ def source
257
+ driver.page_source
258
+ end
259
+ def url
260
+ driver.current_url
261
+ end
262
+ def title
263
+ driver.title
264
+ end
265
+
266
+ end
@@ -0,0 +1,7 @@
1
+ class SK::Button < SK::Clickable
2
+
3
+ def initialize(locator,delay: 2)
4
+ super(locator,delay: delay)
5
+ end
6
+
7
+ end
@@ -0,0 +1,22 @@
1
+ class SK::Clickable < SK::Element
2
+
3
+ # a clickable element can be created with a custom delay
4
+ # so that the tester does not have to set the delay at
5
+ # every calling point... just once at the creation oint
6
+
7
+ def initialize(locator,delay: 0)
8
+ super(locator) # creates the el and locator
9
+ @delay = delay
10
+ end
11
+
12
+ def click(delay = @delay)
13
+ if self.el
14
+ # SK::Trace.trace "SK::Clickable.click #{self.locator} #{self.el}"
15
+ self.el.click
16
+ sleep delay
17
+ else
18
+ SK::Trace.error "SK::Clickable.click: element not initialized for #{locator}"
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,80 @@
1
+ module SK::Downloads
2
+
3
+ @path = nil
4
+
5
+ extend self
6
+
7
+ def path=(p)
8
+ @path = p
9
+ end
10
+
11
+ def path
12
+ @path = @path || determine_mac_path
13
+ end
14
+
15
+ def determine_mac_path
16
+ parts = File.dirname(__FILE__).split("/")
17
+ # will work for AR and PC on a Mac (for now)
18
+ "/#{parts[1]}/#{parts[2]}/downloads"
19
+ end
20
+
21
+ def files
22
+ # NOTE: every time this is called it goes out to the OS for
23
+ # a fresh list of the files... we may want to change to a
24
+ # "refresh" or "readfiles" model for performance
25
+ Dir["#{self.path}/*"]
26
+ end
27
+
28
+ def names
29
+ files.collect {|f| File.basename(f) }
30
+ end
31
+
32
+ def include?(filename)
33
+ filepath = "#{path}/#{filename}"
34
+ files.include? filepath
35
+ end
36
+
37
+ def last
38
+ files.max_by {|f| File.mtime(f)}
39
+ end
40
+
41
+ def last_name
42
+ File.basename last # just the file name
43
+ end
44
+
45
+ def count
46
+ files.length
47
+ end
48
+
49
+ # def first
50
+ # files.first
51
+ # end
52
+
53
+ # def first_content
54
+ # wait_for_download
55
+ # File.read(first)
56
+ # end
57
+
58
+ def wait_for_download
59
+ Timeout.timeout(1) do
60
+ sleep 0.1 until downloaded?
61
+ end
62
+ end
63
+
64
+ def downloaded?
65
+ !downloading? && files.any?
66
+ end
67
+
68
+ def downloading?
69
+ files.grep(/\.part$/).any?
70
+ end
71
+
72
+ def delete_any(name)
73
+ list = files.select { |f| File.basename(f).include?(name) }
74
+ FileUtils.rm_f(list)
75
+ end
76
+
77
+ def delete_all
78
+ FileUtils.rm_f(files)
79
+ end
80
+ end
@@ -0,0 +1,30 @@
1
+ class SK::Dropdown < SK::Element
2
+
3
+ def initialize(locator)
4
+ super(locator) # creates the el and locator via
5
+ SK::Trace.warn "Dropdown failed to initialize. locator = #{locator}" unless el
6
+ @options = el.find_elements(tag_name: "option")
7
+ end
8
+
9
+ def select(value)
10
+ select_by('text',value)
11
+ end
12
+
13
+ def select_by(attr,value)
14
+ @options.each do |option|
15
+ optval = option.attribute(attr)
16
+ # trace "looking at #{optval}"
17
+ if optval == value
18
+ option.click
19
+ break
20
+ end
21
+ end
22
+ end
23
+
24
+ def select_index(index)
25
+ n = [@options.length-1,index].min
26
+ @options[n].click
27
+ return @options[n].attribute('text')
28
+ end
29
+
30
+ end
@@ -0,0 +1,104 @@
1
+ class SK::Element
2
+
3
+ def initialize(arg,src="xxx")
4
+ # puts "element init arg=#{arg} src=#{src}"
5
+ if !arg
6
+ # sometimes we want to create an element from
7
+ # a find that fails... so create a dummy element
8
+ @locator = { src: src }
9
+ @el = false
10
+ elsif arg.instance_of?(Selenium::WebDriver::Element)
11
+ @locator = { src: src }
12
+ @el = arg
13
+ else # it is a locator
14
+ @locator = arg # remember
15
+ @el = SK::Browser.find(arg)
16
+ SK::Trace.debug "element locator=#{arg} el=#{@el}"
17
+ SK::Trace.warn "element failed to initialize with locator = #{arg}" unless @el
18
+ end
19
+ end
20
+
21
+ attr_reader :el
22
+ attr_reader :locator
23
+
24
+ def to_s
25
+ "<SK::Element #{locator}>"
26
+ end
27
+
28
+ def exists?
29
+ !!el
30
+ end
31
+ alias :exist? :exists?
32
+
33
+ def displayed?
34
+ puts "+++ element displayed?"
35
+ SK::Browser.rescue_exceptions { self.el.displayed? }
36
+ end
37
+
38
+ def html
39
+ # useful to see for debugging
40
+ self.el.attribute('innerHTML')
41
+ end
42
+
43
+ def enabled?
44
+ puts "enabled? 1:#{exists?}"
45
+ false unless exists?
46
+ puts "enabled? 2:#{el.enabled?}"
47
+ el.enabled?
48
+ end
49
+
50
+ def text
51
+ # useful to see contents for debugging
52
+ str1 = self.el ? self.el.text : ''
53
+ # str2 = str1.gsub(/\n\s+/, " ") # shrink white space
54
+ str1.gsub(/\n+/, " ").strip # remove new lines
55
+ end
56
+
57
+ def find(locator,klass=SK::Element)
58
+ # trace "find #{locator} in #{self.locator}"
59
+ child_el = find_child_el(locator)
60
+ # trace "child el = #{child_el}"
61
+ klass.new(child_el,"#{locator}")
62
+ end
63
+ alias :child :find
64
+
65
+ def find_child_el(locator)
66
+ # trace "find child of #{self.locator}. locator=#{locator}"
67
+ # find an element by locator inside another element (base)
68
+ case
69
+ when locator.has_key?(:value)
70
+ # trace "... locate by value: #{locator[:value]}}"
71
+ search(:value,locator[:value])
72
+ when locator.has_key?(:type)
73
+ # trace "... locate by type: #{locator[:type]}"
74
+ search(:type,locator[:type])
75
+ else
76
+ # a standard selenium locator so just use selenium
77
+ SK::Browser.rescue_exceptions { self.el.find_element(locator) }
78
+ end
79
+ end
80
+
81
+ def children(locator,klass=SK::Element)
82
+ # get the matching children elements
83
+ els = SK::Browser.rescue_exceptions { self.el.find_elements(locator) }
84
+ # but return as one of our class types
85
+ els.map { |el| klass.new(el) }
86
+ end
87
+
88
+ def search(key,val)
89
+ trace "element#search key=#{key} val=#{val}"
90
+ # selenium does not support a locator search by type
91
+ # so we need a specialized function to find the element
92
+ elements = self.el.find_elements({})
93
+ #elements = all({tag_name: 'input'})
94
+ elements.find do |e|
95
+ # trace "> #{e.attribute(key)} :: #{val}"
96
+ e.attribute(key) == val
97
+ end
98
+ end
99
+
100
+ def parent_el
101
+ self.el.find_element({xpath: ".."})
102
+ end
103
+
104
+ end
@@ -0,0 +1,16 @@
1
+ class SK::Field < SK::Element
2
+
3
+ def initialize(locator)
4
+ super(locator) # creates the el and locator
5
+ end
6
+
7
+ def set(value)
8
+ if self.el
9
+ self.el.clear
10
+ self.el.send_keys(value)
11
+ else
12
+ SK::Trace.error "SK::Field.set: element not initialized for #{locator}"
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,138 @@
1
+ class SK::KElement
2
+
3
+ def initialize(el)
4
+ @element = el
5
+ end
6
+
7
+ def el
8
+ @element
9
+ end
10
+
11
+ def exists?
12
+ !!el
13
+ end
14
+
15
+ def text
16
+ # useful to see for debugging
17
+ self.el.text
18
+ end
19
+
20
+ def html
21
+ # useful to see for debugging
22
+ self.el.attribute('innerHTML')
23
+ end
24
+
25
+ end
26
+
27
+ class SK::KCell < SK::KElement
28
+ def as_num
29
+ # trace "cell = #{cell.text}"
30
+ sign = self.text.include?('(') ? -1 : 1
31
+ sign * self.text.gsub(/[$,()]/, '').to_f
32
+ end
33
+ end
34
+
35
+ class SK::KRow < SK::KElement
36
+ def cells()
37
+ self.el.find_elements({tag_name: 'td'}).collect{ |e| SK::KCell.new(e) }
38
+ end
39
+ end
40
+
41
+ class SK::KGrid < SK::KElement
42
+ def initialize(locator={id: 'grid'})
43
+ super(SK::Browser.find(locator))
44
+ end
45
+ def grid
46
+ el
47
+ end
48
+ def items_label()
49
+ return nil unless grid
50
+ self.grid.find_element({class: 'k-pager-info'})
51
+ end
52
+ def items_count()
53
+ return 0 unless self.grid
54
+ return 0 unless self.items_label
55
+ # trace "*** items label = #{self.items_label.text}"
56
+ count = /(\d*) items/.match(self.items_label.text)[1].to_i
57
+ return count
58
+ end
59
+ def pages_count
60
+ last_page_button.attribute('data-page').to_i
61
+ end
62
+ def last_page_button
63
+ self.grid.find_element({class: 'k-pager-last'})
64
+ end
65
+ def first_page_button
66
+ self.grid.find_element({class: 'k-pager-first'})
67
+ end
68
+ def prev_page_button
69
+ # there is an easily identifiable span inside the button
70
+ span = self.grid.find_element({class: 'k-i-arrow-w'})
71
+ span.find_element({xpath: '..'})
72
+ end
73
+ def next_page_button
74
+ # there is an easily identifiable span inside the button
75
+ span = self.grid.find_element({class: 'k-i-arrow-e'})
76
+ span.find_element({xpath: '..'})
77
+ end
78
+ def rows
79
+ set = self.grid.find_elements({tag_name: 'tr'})
80
+ # trace "wt grid rows length = #{set.length}"
81
+ set
82
+ end
83
+ def row(n)
84
+ SK::KRow.new(self.rows[n])
85
+ end
86
+
87
+ end
88
+
89
+ class SK::KFilter
90
+ def initialize(n)
91
+ @filter = nil # in case of error
92
+ # first check that the current page has a kendo grid
93
+ grid = SK::KGrid.new()
94
+ return if ! grid
95
+ # then work our way throught the page/grid...
96
+ # list of all the column headers; this is a little
97
+ # fragile if the page has other tables before the grid
98
+ th_list = SK::Browser.all({tag_name: 'th'})
99
+ return if !th_list
100
+ return if th_list.length < n
101
+ header = th_list[n] # the nth header for the column
102
+ # puts "attribute = #{header.attribute('data-field')}"
103
+ @filter = header.find_element({class: 'k-grid-filter'})
104
+ # puts "find filter = #{@filter}"
105
+ end
106
+ def click
107
+ # puts "click filter = #{@filter}"
108
+ @filter.click() # makes AC it visible
109
+ # pause 1
110
+ end
111
+ def clear
112
+ buttons = SK::Browser.all({tag_name: 'button'})
113
+ button = buttons.find { |el| el.text == 'Clear' }
114
+ button.click if button
115
+ sleep 1
116
+ end
117
+ def select(value)
118
+ containers = SK::Browser.all({class: 'k-animation-container'})
119
+ container = containers.find { |c| c.displayed? }
120
+ sleep 1 # to find the textbox???
121
+ textbox = container.find_element({class: 'k-textbox'})
122
+ trace "filter's textbox is not visisble" unless textbox.displayed?
123
+ textbox.send_keys(value)
124
+ button = container.find_element({class: 'k-primary'})
125
+ button.click()
126
+ sleep 1
127
+ end
128
+ end
129
+
130
+ module SK::Kendo
131
+ class << self
132
+
133
+ def grid()
134
+ return SK::KGrid.new()
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,7 @@
1
+ class SK::Link < SK::Clickable
2
+
3
+ def initialize(locator,delay: 1)
4
+ super(locator,delay: delay)
5
+ end
6
+
7
+ end
@@ -0,0 +1,62 @@
1
+ # TODO: move some of the browser methods to page
2
+
3
+ class SK::Page
4
+
5
+ def initialize(base,page)
6
+ @url = "#{base}/#{page}"
7
+ end
8
+
9
+ def url
10
+ @url
11
+ end
12
+
13
+ # def goto
14
+ # SK::Browser.gotox(url)
15
+ # end
16
+
17
+ def goto(opts={})
18
+ query = opts.map { |k,v| k.to_s+"="+v.to_s }.join("&")
19
+ url = @url
20
+ url += "?" + query unless query == ""
21
+ trace("goto: url=#{url}")
22
+ SK::Browser.gotox(url)
23
+ end
24
+
25
+
26
+ def present?
27
+ urls_match?
28
+ end
29
+
30
+ def urls_match?
31
+ # change to the looser include instead of equal
32
+ return true if SK::Browser.url.include? self.url
33
+
34
+ # return true if SK::Browser.url == self.url # old code
35
+
36
+ # because we almost always need to see some clues when the expected page is
37
+ # not present we trace some outpout the the tester
38
+ trace "SK::Page url_match? expected: #{url} did not match current: #{SK::Browser.url}"
39
+ false # returned
40
+ end
41
+
42
+ def has_content?(content)
43
+ result = SK::Browser.source.include? content
44
+ # trace "missing content = #{content}" unless result
45
+ return result
46
+ end
47
+
48
+ def here?(text)
49
+ return false unless urls_match?
50
+ # urls do match, but also require that
51
+ has_content? text
52
+ end
53
+
54
+ def source
55
+ SK::Browser.source
56
+ end
57
+
58
+ def title
59
+ SK::Browser.title
60
+ end
61
+
62
+ end
@@ -0,0 +1,20 @@
1
+ class SK::RadioSet
2
+
3
+ def initialize(locator)
4
+ # get all the elements for the radio
5
+ @els = SK::Browser.all(locator)
6
+ # trace("radio els = #{@els}")
7
+ end
8
+
9
+ def select(value)
10
+ # trace("radio els = #{@els}")
11
+ @els.each do |el|
12
+ #trace "radio looking at #{el.text}: #{value}"
13
+ if el.attribute('value') == value
14
+ el.click
15
+ break
16
+ end
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,83 @@
1
+ require 'selenium-webdriver'
2
+
3
+ # NOTE: the requires are at bottom
4
+
5
+ module SK
6
+
7
+ @driver = nil
8
+
9
+ extend self
10
+
11
+ def version
12
+ v = "0.0.1"
13
+ # Trace.trace "version: #{v}"
14
+ return v
15
+ end
16
+
17
+ def init(seconds=2, browser=:safari)
18
+
19
+ # browser_stack_url = "http://patconley2:LBqJyYGj5TsyNBWe2Bjy@hub.browserstack.com/wd/hub"
20
+ # $driver = Selenium::WebDriver.for(:remote, :url => browser_stack_url)
21
+
22
+ # Trace.trace "SK::init"
23
+ # seconds = max time to wait for the element to appear
24
+ wait = Selenium::WebDriver::Wait.new(:timeout => seconds)
25
+
26
+ profile = Selenium::WebDriver::Firefox::Profile.new
27
+ profile["javascript.enabled"] = false # NOT SURE WHY????
28
+ # trace "wt init download path = #{SK::Downloads.path}"
29
+ profile['browser.download.dir'] = SK::Downloads.path
30
+ #
31
+ # # The value of browser.download.folderList can be set to either 0, 1, or 2.
32
+ # # When set to 0, Firefox will save all files downloaded via the browser on the
33
+ # # user's desktop. When set to 1, these downloads are stored in the Downloads folder.
34
+ # # When set to 2, the location specified for the most recent download is utilized again
35
+ profile['browser.download.folderList'] = 2 # use the specified directory
36
+
37
+ # Suppress "open with" dialog for a file types
38
+ profile['browser.helperApps.neverAsk.saveToDisk'] = "text/csv,application/pdf,application/xls,image/tiff"
39
+ profile['browser.helperApps.alwaysAsk.force'] = false
40
+ # disable Firefox's built-in PDF viewer
41
+ profile["pdfjs.disabled"] = true
42
+ # disable Adobe Acrobat PDF preview plugin
43
+ profile["plugin.scan.plid.all"] = false
44
+ profile["plugin.scan.Acrobat"] = "99.0"
45
+
46
+ @driver = Selenium::WebDriver.for(browser)
47
+
48
+ # NOTE 3/4/17 the profile code failed for safari... see use of FIREFOX in creating profile!!
49
+
50
+ # @driver = Selenium::WebDriver.for(browser, :profile => profile)
51
+ # $driver = Selenium::WebDriver.for :firefox # :safari :chrome
52
+
53
+ # TODO: what does this do... overried the above???
54
+ # @driver.manage.timeouts.implicit_wait = 5
55
+
56
+ @driver # returned ????
57
+ end
58
+
59
+ def quit
60
+ # Trace.trace "SK::quit"
61
+ driver.quit if driver
62
+ @driver = nil
63
+ end
64
+
65
+ def driver
66
+ @driver
67
+ end
68
+
69
+ end
70
+
71
+ require 'shiken/trace'
72
+ require 'shiken/browser'
73
+ require 'shiken/page'
74
+ require 'shiken/element'
75
+ require 'shiken/field'
76
+ require 'shiken/clickable'
77
+ require 'shiken/button'
78
+ require 'shiken/link'
79
+ require 'shiken/dropdown'
80
+ require 'shiken/radio_set'
81
+ require 'shiken/kendo'
82
+ require 'shiken/table'
83
+ require 'shiken/downloads'
@@ -0,0 +1,56 @@
1
+ class SK::Cell < SK::Element
2
+
3
+ # row is an element that "remembers" it's index in the row
4
+
5
+ attr_reader :index
6
+
7
+ def initialize(locator,index)
8
+ super(locator) # creates the el and locator
9
+ @index = index # remember your position
10
+ end
11
+
12
+ def as_num
13
+ # trace "cell = #{cell.text}"
14
+ sign = self.text.include?('(') ? -1 : 1
15
+ sign * self.text.gsub(/[$,()]/, '').to_f
16
+ end
17
+
18
+ def to_s
19
+ "<SK::Cell #{@index} [#{self.text}]>"
20
+ end
21
+
22
+ end
23
+
24
+ class SK::Row < SK::Element
25
+
26
+ # row is an element that "remembers" it's index in the table
27
+
28
+ attr_reader :index
29
+
30
+ def initialize(locator,index)
31
+ super(locator) # creates the el and locator
32
+ @index = index # remember your position
33
+ end
34
+
35
+ def cells()
36
+ ds = self.el.find_elements({tag_name: 'td'})
37
+ ds.map.with_index { |e,i| SK::Cell.new(e,i) }
38
+ end
39
+
40
+ def to_s
41
+ text = cells.map { |cell| cell.text }.join("][")
42
+ "<SK::Row #{@index} [#{text}] >"
43
+ end
44
+ end
45
+
46
+ class SK::Table < SK::Element
47
+
48
+ def rows
49
+ rs = self.el.find_elements({tag_name: 'tr'})
50
+ SK::Trace.debug "SK::Table el rows length = #{rs.length}"
51
+ ws = rs.map.with_index { |r,i| SK::Row.new(r,i) }
52
+ SK::Trace.debug "SK::Table wt rows length = #{ws.length}"
53
+ ws # returned
54
+ end
55
+
56
+ end
@@ -0,0 +1,59 @@
1
+ require 'colorize'
2
+
3
+ module SK::Trace
4
+
5
+ DEBUG = 3
6
+ WARN = 2
7
+ ERROR = 1
8
+ QUIET = 0
9
+
10
+ extend self
11
+
12
+ @level = DEBUG
13
+
14
+ def level=(value)
15
+ case value
16
+ when :debug
17
+ n = DEBUG
18
+ when :warn
19
+ n = WARN
20
+ when :error
21
+ n = ERROR
22
+ when :quiet
23
+ n = QUIET
24
+ else
25
+ n = value.to_i
26
+ end
27
+ @level = n
28
+ end
29
+
30
+ def level
31
+ @level
32
+ end
33
+
34
+ def trace(s)
35
+ write "SK::Trace : #{s}".cyan, DEBUG
36
+ end
37
+ def debug(s)
38
+ write "SK::Debug : #{s}".cyan, DEBUG
39
+ end
40
+ def error(s)
41
+ write "SK::Error: #{s}".red, ERROR
42
+ end
43
+ def notice(s)
44
+ write "SK::Notice: #{s}".yellow, WARN
45
+ end
46
+ def warn(s)
47
+ write "SK::Warn : #{s}".yellow, WARN
48
+ end
49
+
50
+ def write(text,lev)
51
+ puts text if level >= lev
52
+ end
53
+
54
+ # def xfail(num,s)
55
+ # error num, s
56
+ # fail
57
+ # end
58
+
59
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shiken
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Pat Conley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-01-05 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A layer to simplify ruby use of selenium
14
+ email: pconley312@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/browser.rb
20
+ - lib/button.rb
21
+ - lib/clickable.rb
22
+ - lib/downloads.rb
23
+ - lib/dropdown.rb
24
+ - lib/element.rb
25
+ - lib/field.rb
26
+ - lib/kendo.rb
27
+ - lib/link.rb
28
+ - lib/page.rb
29
+ - lib/radio_set.rb
30
+ - lib/shiken.rb
31
+ - lib/table.rb
32
+ - lib/trace.rb
33
+ homepage: https://github.com/pconley/Shiken.git
34
+ licenses:
35
+ - MIT
36
+ metadata: {}
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project:
53
+ rubygems_version: 2.5.1
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: A Selenium Facade in Ruby
57
+ test_files: []