Class: Element

Inherits:
Object
  • Object
show all
Defined in:
lib/element.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, by, locator) ⇒ Element

Returns a new instance of Element.



8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/element.rb', line 8

def initialize(name, by, locator)
  @name = name
  @by = by
  @locator = locator
  @element_screenshot = nil #used to store the path of element screenshots for comparison

  # wrapped driver
  @driver = Driver.driver

  # selenium web element
  @element = nil
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_sym, *arguments, &block) ⇒ Object



303
304
305
306
307
308
309
310
# File 'lib/element.rb', line 303

def method_missing(method_sym, *arguments, &block)
  Log.debug("called #{method_sym} on element #{@locator} by #{@by_type}")
  if @element.respond_to?(method_sym)
    @element.method(method_sym).call(*arguments, &block)
  else
    super
  end
end

Instance Attribute Details

#byObject (readonly)

Returns the value of attribute by.



6
7
8
# File 'lib/element.rb', line 6

def by
  @by
end

#locatorObject (readonly)

Returns the value of attribute locator.



6
7
8
# File 'lib/element.rb', line 6

def locator
  @locator
end

#nameObject (readonly)

Returns the value of attribute name.



6
7
8
# File 'lib/element.rb', line 6

def name
  @name
end

Instance Method Details

#attribute(name) ⇒ Object



81
82
83
# File 'lib/element.rb', line 81

def attribute(name)
  element.attribute(name)
end

#clearObject



101
102
103
# File 'lib/element.rb', line 101

def clear
  element.clear
end

#clickObject



105
106
107
108
109
110
111
112
113
114
# File 'lib/element.rb', line 105

def click
  Log.debug("Clicking on #{self}")
  if element.enabled?
    ElementExtensions.highlight(self) if Gridium.config.highlight_verifications
    $verification_passes += 1
    element.click
  else
    Log.error('Cannot click on element.  Element is not present.')
  end
end

#compare_element_screenshot(base_image_path) ⇒ Object



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/element.rb', line 264

def compare_element_screenshot(base_image_path)
  #Returns TRUE if there are no differences, FALSE if there are
  begin
    Log.debug("Loading Images for Comparison...")
    images = [
        ChunkyPNG::Image.from_file(base_image_path),
        ChunkyPNG::Image.from_file(@element_screenshot)
    ]
    #used to store image x,y diff
    diff = []
    Log.debug("Comparing Images...")
    images.first.height.times do |y|
      images.first.row(y).each_with_index do |pixel, x|
        diff << [x,y] unless pixel == images.last[x,y]
      end
    end

    Log.debug("Pixels total:    #{images.first.pixels.length}")
    Log.debug("Pixels changed:  #{diff.length}")
    Log.debug("Pixels changed:  #{(diff.length.to_f / images.first.pixels.length) * 100}%")

    x, y = diff.map{|xy| xy[0]}, diff.map{|xy| xy[1]}

    if x.any? && y.any?
      Log.debug("Differences Detected! Writing Diff Image...")
      name = self.name.gsub(' ', '_')
      #timestamp = Time.now.strftime("%Y_%m_%d__%H_%M_%S")
      element_screenshot_path = File.join($current_run_dir, "#{name}__diff_.png")
      images.last.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color(0,255,0))
      images.last.save(element_screenshot_path)
      return false
    else
      return true
    end
  rescue Exception => e
    Log.error("There was a problem comparing element images. #{e.to_s}")
  end
end

#displayed?Boolean

Returns:

  • (Boolean)


91
92
93
94
95
# File 'lib/element.rb', line 91

def displayed?
  return element.displayed?
rescue StandardError
  return false
end

#displayed_elementObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/element.rb', line 42

def displayed_element
  found_element = nil
  #Found an issue where the element would go stale after it's found
  begin
    elements = @driver.find_elements(@by, @locator)
    elements.each do |element|
      if element.displayed? #removed check for element.enabled
        found_element = element; #this will always return the last displayed element
      end
    end
  rescue StandardError
    if found_element
      Log.warn("An element was found, but it was not displayed on the page. Gridium.config.visible_elements_only set to: #{Gridium.config.visible_elements_only} Element: #{self.to_s}")
    else
      Log.warn("Could not find Element: #{self.to_s}")
    end
  end

  found_element
end

#elementObject



25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/element.rb', line 25

def element
  if stale?
    wait = Selenium::WebDriver::Wait.new :timeout => Gridium.config.element_timeout, :interval => 1
    if Gridium.config.visible_elements_only
      wait.until { @element = displayed_element }
    else
      wait.until { @element = @driver.find_element(@by, @locator); Log.debug("Finding element #{self}..."); @element.enabled? }
    end

  end
  @element
end

#element=(e) ⇒ Object



38
39
40
# File 'lib/element.rb', line 38

def element=(e)
  @element = e
end

#enabled?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/element.rb', line 97

def enabled?
  element.enabled?
end

#find_element(by, locator) ⇒ Element

Search for an element within this element

Parameters:

  • by (Symbol)

    (:css or :xpath)

  • locator (String)

Returns:



223
224
225
226
# File 'lib/element.rb', line 223

def find_element(by, locator)
  Log.debug('Finding element...')
  element.find_element(by, locator)
end

#find_elements(by, locator) ⇒ Array

Search for an elements within this element

Parameters:

  • by (Symbol)

    (:css or :xpath)

  • locator (String)

Returns:

  • (Array)

    elements



236
237
238
# File 'lib/element.rb', line 236

def find_elements(by, locator)
  element.find_elements(by, locator)
end

#hover_awayObject



144
145
146
147
148
149
150
151
152
# File 'lib/element.rb', line 144

def hover_away
  Log.debug("Hovering away from element (#{self.to_s})...")
  if element.enabled?
    $verification_passes += 1
    ElementExtensions.hover_away(self) # Javascript workaround to above issue
  else
    Log.error('Cannot hover away from element.  Element is not present.')
  end
end

#hover_overObject



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/element.rb', line 131

def hover_over
  Log.debug("Hovering over element (#{self.to_s})...")
  # @driver.mouse.move_to(element)            # Note: Doesn't work with Selenium 2.42 bindings for Firefox v31
  # @driver.action.move_to(element).perform
  # @driver.mouse_over(@locator)
  if element.enabled?
    $verification_passes += 1
    ElementExtensions.hover_over(self) # Javascript workaround to above issue
  else
    Log.error('Cannot hover over element.  Element is not present.')
  end
end

#locationObject



127
128
129
# File 'lib/element.rb', line 127

def location
  element.location
end

#mouse_overObject

Raw webdriver mouse over



155
156
157
158
159
160
161
162
163
# File 'lib/element.rb', line 155

def mouse_over
  Log.debug("Triggering mouse over for (#{self.to_s})...")
  if element.enabled?
    $verification_passes += 1
    ElementExtensions.mouse_over(self)
  else
    Log.error('Cannot mouse over.  Element is not present.')
  end
end

#present?Boolean

Returns:

  • (Boolean)


85
86
87
88
89
# File 'lib/element.rb', line 85

def present?
  return element.enabled?
rescue StandardError
  return false
end

#save_element_screenshotObject



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/element.rb', line 240

def save_element_screenshot
  Log.debug ("Capturing screenshot of element...")
  self.scroll_into_view

  timestamp = Time.now.strftime("%Y_%m_%d__%H_%M_%S")
  name = self.name.gsub(' ', '_')
  screenshot_path = File.join($current_run_dir, "#{name}__#{timestamp}.png")
  @driver.save_screenshot(screenshot_path)

  location_x = self.location.x
  location_y = self.location.y
  element_width = self.size.width
  element_height = self.size.height

  # ChunkyPNG commands tap into oily_png (performance-enhanced version of chunky_png)
  image = ChunkyPNG::Image.from_file(screenshot_path.to_s)
  image1 = image.crop(location_x, location_y, element_width, element_height)
  image2 = image1.to_image
  element_screenshot_path = File.join($current_run_dir, "#{name}__#{timestamp}.png")
  image2.save(element_screenshot_path)
  @element_screenshot = element_screenshot_path
  SpecData.screenshots_captured.push("#{name}__#{timestamp}.png")
end

#scroll_into_viewObject



165
166
167
168
169
170
171
172
# File 'lib/element.rb', line 165

def scroll_into_view
  if element.enabled?
    $verification_passes += 1
    ElementExtensions.scroll_to(self)
  else
    Log.error('Cannot scroll element into view.  Element is not present.')
  end
end

#selected?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'lib/element.rb', line 188

def selected?
  element.selected?
end

#send_keys(*args) ⇒ Object



116
117
118
119
120
121
122
123
124
125
# File 'lib/element.rb', line 116

def send_keys(*args)
  Log.debug("Typing: #{args} into element: (#{self}).")
  if element.enabled?
    ElementExtensions.highlight(self) if Gridium.config.highlight_verifications
    $verification_passes += 1
    element.send_keys(*args)
  else
    Log.error('Cannot type into element.  Element is not present.')
  end
end

#sizeObject



184
185
186
# File 'lib/element.rb', line 184

def size
  element.size
end

#submitObject



196
197
198
# File 'lib/element.rb', line 196

def submit
  element.submit
end

#tag_nameObject



192
193
194
# File 'lib/element.rb', line 192

def tag_name
  element.tag_name
end

#textObject



200
201
202
203
# File 'lib/element.rb', line 200

def text
  #this is used for text based elements
  element.text
end

#text=(text) ⇒ Object



205
206
207
208
# File 'lib/element.rb', line 205

def text=(text)
  element.clear
  element.send_keys(text)
end

#to_sObject



21
22
23
# File 'lib/element.rb', line 21

def to_s
  "'#{@name}' (By:#{@by} => '#{@locator}')"
end

#trigger_onblurObject



174
175
176
177
178
179
180
181
182
# File 'lib/element.rb', line 174

def trigger_onblur
  Log.debug("Triggering onblur for (#{self.to_s})...")
  if element.enabled?
    $verification_passes += 1
    ElementExtensions.trigger_onblur(self)
  else
    Log.error('Cannot trigger onblur.  Element is not present.')
  end
end

#valueObject



210
211
212
213
# File 'lib/element.rb', line 210

def value
  #this is used for inputs and forms
  element.attribute("value")
end

#verify(timeout: nil) ⇒ Object

soft failure, will not kill test immediately



68
69
70
71
72
# File 'lib/element.rb', line 68

def verify(timeout: nil)
  Log.debug('Verifying new element...')
  timeout = Gridium.config.element_timeout if timeout.nil?
  ElementVerification.new(self, timeout)
end

#wait_until(timeout: nil) ⇒ Object

hard failure, will kill test immediately



75
76
77
78
79
# File 'lib/element.rb', line 75

def wait_until(timeout: nil)
  Log.debug('Waiting for new element...')
  timeout = Gridium.config.element_timeout if timeout.nil?
  ElementVerification.new(self, timeout, fail_test: true)
end