Class: Marta::BlackMagic::MagicFinder

Inherits:
BasicFinder
  • Object
show all
Includes:
ElementInformation, OptionsAndPaths, PageArithmetic, ReadWrite
Defined in:
lib/marta/black_magic.rb

Overview

Note:

It is believed that no user will use it

Element searching class.

Instance Method Summary collapse

Constructor Details

#initialize(meth, tolerancy, name, requestor) ⇒ MagicFinder

Returns a new instance of MagicFinder.



34
35
36
37
38
39
40
# File 'lib/marta/black_magic.rb', line 34

def initialize(meth, tolerancy, name, requestor)
  @tolerancy = tolerancy
  @engine = requestor.engine
  @name = name
  @requestor = requestor
  super(meth, requestor)
end

Instance Method Details

#actual_searching(result) ⇒ Object

The core of Black Magic Algorithm



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/marta/black_magic.rb', line 187

def actual_searching(result)
  granny, pappy, i = true, true, 1
  while !result.exists?
    array_of_xpaths = form_complex_xpath(i, granny, pappy)
    if XPathFactory.new(@meth, @requestor).analyze(i, @tolerancy)[0] < i
      # One more step.
      # We will try to exclude grandparent element data at first.
      # Then we will try to exclude parent.
      # Finally we will try to exclude all the parents.
      # If they are already excluded and Marta is out of tolerancy...
      granny, pappy, i = granny_pappy_manage(granny, pappy) + [1]
      array_of_xpaths = form_complex_xpath(i, granny, pappy)
    end
    array_of_elements,
      array_of_els_xpaths = candidates_arrays_creation(array_of_xpaths)
    i += 1
    result =
        get_search_result(result, array_of_elements, array_of_els_xpaths)
  end
  return result
end

#candidates_arrays_creation(array_of_xpaths) ⇒ Object

We are forming arrays of candidates



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/marta/black_magic.rb', line 137

def candidates_arrays_creation(array_of_xpaths)
  array_of_elements, array_of_els_xpaths = Array.new, Array.new
  something = nil
  array_of_xpaths.each do |xpath|
    something = @engine.elements(xpath: xpath)
    if something.to_a.length > 0
      array_of_elements += something.to_a
      something.to_a.length.times {array_of_els_xpaths.push xpath}
    end
  end
  return array_of_elements, array_of_els_xpaths
end

#findObject

Main method. It finds an element



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/marta/black_magic.rb', line 84

def find
  if !forced_xpath?
    element = prefind_with_waiting
    if !element.exists?
      warn_and_search element
      if collection?
        return_collection
      else
        return_element
      end
    end
  end
  super
end

#form_complex_xpath(unknowns, granny = true, pappy = true) ⇒ Object

Marta can form special xpath guess for element finding attempt



112
113
114
115
116
117
118
119
120
121
# File 'lib/marta/black_magic.rb', line 112

def form_complex_xpath(unknowns, granny=true, pappy=true)
  xpath_factory = XPathFactory.new(@meth, @requestor)
  xpath_factory.granny = granny
  xpath_factory.pappy = pappy
  if xpath_factory.array_of_hashes.count <= unknowns
    raise "Marta did her best. But she found nothing"
  else
    xpath_factory.generate_xpaths(unknowns, @tolerancy)
  end
end

#get_result_inputs(array_of_elements) ⇒ Object

Getting indexes of the most common element in the array of suggested elements



164
165
166
167
168
169
# File 'lib/marta/black_magic.rb', line 164

def get_result_inputs(array_of_elements)
  result = array_of_elements.group_by(&:itself).
           values.max_by(&:size).first
  array_of_elements.each_index.
                          select{|i| array_of_elements[i] == result}
end

#get_search_result(result, array_of_elements, array_of_els_xpaths) ⇒ Object

Selecting the most common element in the array.



151
152
153
154
155
156
157
158
159
160
# File 'lib/marta/black_magic.rb', line 151

def get_search_result(result, array_of_elements, array_of_els_xpaths)
  something = result
  if array_of_elements.size > 0
    inputs = get_result_inputs(array_of_elements)
    most_uniq_xpath_by_inputs(array_of_els_xpaths, inputs)
    array_of_elements[array_of_els_xpaths.index(@xpath)]
  else
    something
  end
end

#granny_pappy_manage(granny, pappy) ⇒ Object

We should manage granny, pappy and i values for additional steps



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/marta/black_magic.rb', line 124

def granny_pappy_manage(granny, pappy)
  if !(granny or pappy)
    raise "Marta did her best. But she found nothing"
  end
  if (granny and pappy) or (granny and !pappy)
    granny = false
  else
    granny, pappy = true, false
  end
  return granny, pappy
end

#most_uniq_xpath_by_inputs(array_of_els_xpaths, inputs) ⇒ Object

Getting the most specific xpath for the most common element in order to locate it only



173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/marta/black_magic.rb', line 173

def most_uniq_xpath_by_inputs(array_of_els_xpaths, inputs)
  xpaths = Array.new
  array_of_els_xpaths.
         each_with_index{|e, i| xpaths.push e if inputs.include?(i)}
  @xpath = xpaths[0]
  xpaths.each do |x|
    current_count = array_of_els_xpaths.count(x)
    proposed_count = array_of_els_xpaths.count(@xpath)
    @xpath = x if current_count < proposed_count
  end
  @xpath
end

#prefind_with_waitingObject

We can prefind an element and wait for it.



43
44
45
46
47
48
49
50
# File 'lib/marta/black_magic.rb', line 43

def prefind_with_waiting
  begin
    prefind.wait_until_present(timeout: SettingMaster.cold_timeout)
  rescue
    # found nothing
    prefind
  end
end

#return_collectionObject

When black magic is finding some collection it is not only returning it. It is silently generating changes to a json file



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/marta/black_magic.rb', line 54

def return_collection
  result = prefind_collection
  to_save = @meth
  result.each do |item|
    meth_data = method_structure true
    meth_data['positive'] = get_attributes item, @requestor
    to_save = make_collection(to_save, meth_data)
  end
  file_name  = @requestor.instance_variable_get("@class_name").to_s
  file_data = @requestor.instance_variable_get("@data")
  file_data['meths'][@name] = to_save
  file_write(file_name, file_data)
  result
end

#return_elementObject

When black magic is finding some element it is not only returning it. It is silently writing actual data about the element to json



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/marta/black_magic.rb', line 71

def return_element
  result = prefind
  meth_data = method_structure
  meth_data['positive'] = get_attributes result, @requestor
  to_save = forget_unstable(@meth, meth_data)
  file_name  = @requestor.instance_variable_get("@class_name").to_s
  file_data = @requestor.instance_variable_get("@data")
  file_data['meths'][@name] = to_save
  file_write(file_name, file_data)
  subtype_of prefind
end

#warn_and_search(element) ⇒ Object

Marta is producing warning when element was not found normally



100
101
102
103
104
105
106
107
108
109
# File 'lib/marta/black_magic.rb', line 100

def warn_and_search(element)
  warn "ATTENTION: Element "\
       "#{@requestor.instance_variable_get("@class_name")}.#{@name}"\
       " was not found by locator = #{@xpath}."
  warn "And Marta uses a black"\
       " magic to find it. If she finds something"\
       " Marta redefines it without warning."
  actual_searching(element)
  warn "Xpath suggested by Marta  = #{@xpath}"
end