class Marta::BlackMagic::MagicFinder
Element searching class.
@note It is believed that no user will use it
Public Class Methods
# 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
Public Instance Methods
The core of Black Magic Algorithm
# 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
We are forming arrays of candidates
# 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
Main method. It finds an element
# 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
Marta
can form special xpath guess for element finding attempt
# 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
Getting indexes of the most common element in the array of suggested elements
# 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
Selecting the most common element in the array.
# 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
We should manage granny, pappy and i values for additional steps
# 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
Getting the most specific xpath for the most common element in order to locate it only
# 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
We can prefind an element and wait for it.
# 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
When black magic is finding some collection it is not only returning it. It is silently generating changes to a json file
# 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
When black magic is finding some element it is not only returning it. It is silently writing actual data about the element to json
# 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
Marta
is producing warning when element was not found normally
# 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