Files
murano-tests/boffin/build/lib/Boffin/keywords/_Utils.py
Timur Nurlygayanov b2d104d1a1 Cherry-pick changes from release-0.2.
* Added WebUI automated tests
  Ie5dd067f52d4906fc30ac11e820296b7dc797882
* Added scripts for HA testing
  Ib2d7f28458de3fe55f80f3e0955637ba907784b6
* Fixed README.
  I677705d7bc1199632b034f4111fa72ba24ddd71f
* Fixed README again.
  I489578ff1f51685b4b62193f4cd5e61ce8092087
* Fixed IP address in automated tests for API Service
  I10571eec95f9b3ad8e0af0847da94a22a9847b84

Change-Id: I36bc87ec21c3082fe1502a5191c032dc67224bf0
2013-09-10 15:44:34 +04:00

329 lines
10 KiB
Python

# Copyright (c) 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from ConfigParser import ConfigParser
from os import getcwd
from os.path import join
from bs4 import BeautifulSoup
from robot.libraries.BuiltIn import BuiltIn
class _ArtificialIntelligence:
"""
This class allows to find input and select controls \
without manual input of identificators.
We can find input fields by labels near those fields. \
Boffin heart.
"""
ROBOT_LIBRARY_SCOPE = 'GLOBAL'
def __init__(self, page_source):
"""
Class constructor.
*Arguments:*
- page_source: web page source code.
*Return:*
- None.
"""
self.page_source = page_source
def _get_xpath_of_element(self, element):
"""
This function allows to get xpath of soup elements.
*Arguments:*
- element: selector name.
*Return:*
- element xpath.
"""
number = 1
try:
number += len(element.find_previous_siblings(element.name))
except:
pass
xpath = element.name
if number > 1:
xpath += '[' + str(number) + ']'
for parent in element.findParents():
if parent.name != '[document]':
k = 0
for tag in parent.find_previous_siblings():
if tag.name == parent.name:
k += 1
if k == 0:
xpath = parent.name + '/' + xpath
else:
xpath = parent.name + '[' + str(k + 1) + ']/' + xpath
return xpath
def extra_search(self, soup, value, tag=None):
"""
This function allows to get element by its parameters.
*Arguments:*
- soup: soup structure.
- value: element name.
*Return:*
- label_element.
"""
label_element = None
if label_element is None:
label_element = soup.find(tag, text=str(value))
if label_element is None:
label_element = soup.find(tag, attrs={'value': value})
if label_element is None:
label_element = soup.find(tag, attrs={'title': value})
if label_element is None:
try:
for element in soup.find_all(tag):
if str(value) in element.text:
label_element = element
except:
pass
return label_element
def find_element(self, label, element_type='input', method='next',
result='xpath'):
"""
Looks for specified element on the page.
*Arguments:*
- label: selector name.
- element_type: element tag name. It could be any tag or \
several tags (then they are listed as 'select/input/a').
- method: element search method. If 'next' is set, then \
function is looking for the next input field after the \
specified element.
Otherwise it returns the specified element itself.
*Return:*
- element xpath.
*Examples:*
| ${xpath} | Find element | E-mail | input | next |
| ${xpath} | Find element | Cancel | a/div | this |
"""
html = str(self.page_source.encode("utf-8", "replace"))
" load html to soup structure for parsing "
soup = BeautifulSoup(html)
" search element after the label"
try:
element_types = element_type.split('/')
element = None
label_element = self.extra_search(soup, label)
for element_type in element_types:
if method == 'next':
element = label_element.parent.find_next(element_type)
elif method == 'previous':
element = label_element.parent.find_previous(element_type)
elif method == 'associated':
for t in ['a', 'button', 'input', 'select']:
elements = label_element.parent.find_all_next(t)
for e in elements:
if element_type in e.text:
element = e
if element:
break
elements = label_element.parent.find_all_previous(t)
for e in elements:
if element_type in e.text:
element = e
if element:
break
else:
element = self.extra_search(soup, label, element_type)
if element:
break
" return xpath of element "
if result == 'xpath':
return self._get_xpath_of_element(element)
else:
return element
except:
return None
class _Utils(object):
ROBOT_LIBRARY_SCOPE = 'GLOBAL'
def get_element_from_repo(self, element_name):
"""
Returns element type, identificator and frame from \
the 'resources/objrepo/%screen_name%.ini' file by element name.
*Arguments:*
- elementName: screen name and selector name divided by dot.
*Return:*
- <list> [elType, elIdentificator, elFrame].
*Example:*
| @{element} | Get Element From Repo | Home . Banner Page 2 Button |
"""
try:
p = BuiltIn().get_variable_value('${resources_path}')
if p is not None:
_objRepoPath = join(p, 'objrepo')
else:
_objRepoPath = join(getcwd(), 'resources', 'objrepo')
element_name = element_name.lower().replace(' ', '')
print "Element Name: " + element_name
inputElement = element_name.split('.')
if len(inputElement) == 1:
fileName = 'common.ini'
name = element_name
else:
fileName = '%s.ini' % inputElement[0]
name = inputElement[1]
fullFileName = join(_objRepoPath, fileName)
print "fullFileName " + fullFileName
conf = ConfigParser()
conf.read(fullFileName)
print "A: " + conf.get(str(name), 'type')
print "A: " + conf.get(name, 'type')
if not conf.has_section(name):
print name
return ['', None, '']
element_type = conf.get(name, 'type')
element_identificator = ''
element_parent_name = conf.get(name, 'parent')
if element_parent_name:
element_identificator = \
self.get_element_from_repo(element_parent_name)[1] + \
element_identificator
element_identificator += conf.get(name, 'identificator')
element_frame = conf.get(name, 'frame')
return [element_type, element_identificator, element_frame]
except:
return ['', None, '']
def get_web_element_frame(self, elementName):
"""
Returns element frame by its name in the
'resources/objrepo/%screen_name%.ini' file.
*Arguments:*
- elementName: screen name and selector name divided by dot.
*Return:*
- elFrame.
*Example:*
| ${elFrame} | GetElementFrame | Blog . Post Text field |
"""
type, id, frame = self.get_element_from_repo(elementName)
return frame
def get_web_element_selector(self, name, page_source=None,
element_type='input', method='next',
result='xpath'):
"""
Returns element selector by its name in the \
'resources/ObjRepo.ini' file.
*Arguments:*
- name: selector name.
- page_source: web page source code.
- element_type: element tag name. It could be any tag or several \
tags (then they are listed as 'select/input/a').
- method: element search method. If 'next' is set, then function
is looking for the next input field after the specified element.
Otherwise it returns the specified element itself.
*Return:*
- elIdentificator.
*Examples:*
| ${selector} | Get element selector | User Name | ${source_code} \
| input | next |
| ${selector} | Get element selector | Submit Button | ${source_code} \
| a | this |
"""
type, id, frame = self.get_element_from_repo(name)
if not id and page_source:
boffin = _ArtificialIntelligence(page_source)
id = boffin.find_element(name, element_type, method, result)
if result != 'xpath':
return id
if id:
type = 'xpath'
identificator = None
if id:
identificator = '%s%s' % \
('' if not type else '%s=' % str(type), str(id))
return identificator
def get_table_row_xpath(self, page_source, name):
"""
This method allows to parse tables on web pages \
and determine the table row by element from table.
*Arguments:*
- page_source: web page source code.
- name: identificator of row element.
*Return:*
- xpath of table row.
*Example:*
| ${elXpath} | Get Table Row Xpath | Entity 123 |
"""
_type = 'td/a/label/input/select'
element = self.get_web_element_selector(name, page_source,
_type, method='this',
result='element')
tag = element.name
while tag != 'tr' and tag:
try:
tag = element.parent.name
element = element.parent
except:
tag = None
pass
e = _ArtificialIntelligence(page_source)
return e._get_xpath_of_element(element)