# -*- coding: utf-8 -*-
import xlrd
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from behave import step
from helpers import (waitForExtAjax, waitForImport, screenshot,
get_modal_win_id_by_name, get_toolbar_id_by_column_name,
is_tab_with_title_open, get_report_file_name)
from winobject import find_win_obj, get_win_object, Desktop
@step(u'Ввести в поле {element} значение {value}')
[документация]def step_fill_element_with_text(context, element, value):
u"""
Устанавливает значение value в input c атрибутом name равным element.
"""
control = "//input[@name='%s']" % element
elem = context.browser.find_element_by_xpath(control)
elem.send_keys(value)
@step(u'Нажать {element}')
[документация]def step_click_xpath(context, element):
u"""
Ищем кнопку по name
"""
control = "//button[@name='%s']" % element
elem = context.browser.find_element_by_xpath(control)
elem.click()
@step(u'откроется окно {win_obj}')
@screenshot
def step_find_win_obj(context, win_obj):
u"""
Проверка что открылось окно с именем win_obj:
:param win_obj: Название окна.
"""
win = get_win_object(context, win_obj)
assert win.is_open(), 'Window is closed!'
@step(u'закрыть окно {win_obj}')
[документация]def step_close_win(context, win_obj):
u"""
Закрывает окно с именем win_obj.
:param win_obj: Название окна.
"""
win = get_win_object(context, win_obj)
win.close()
@step(u'окно "{win_obj}" не откроется')
[документация]def ste_win_not_open(context, win_obj):
u"""
Проверка того что окно с названием win_obj не открылось.
"""
eval_el = find_win_obj(context, win_obj)
assert win_obj not in eval_el
@step(u'откроется диалоговое окно {win_obj}')
[документация]def step_find_dlg_win(context, win_obj):
u"""
Проверка того что открылось оконо c названием win_obj.
"""
win_id = get_modal_win_id_by_name(context, win_obj)
assert win_id, 'Окно не открыто!'
@step(u'закроется окно {win_obj}')
[документация]def step_check_close_win_obj(context, win_obj):
u"""
Проверка что окно с названием win_obj закрылось.
"""
win = get_win_object(context, win_obj)
assert win.is_close(), 'Window is open!'
@step(u'в окне {win_obj} на вкладке {tab} на '
u'панели инструментов нажать кнопку {button}')
@step(u'в окне {win_obj} на панели инструментов нажать кнопку {button}')
@step(u'в окне {win_obj} в нижней панели нажать кнопку {button}')
@step(u'в окне {win_obj} выбрать первую запись таблицы')
[документация]def step_select_first_row_from_grid(context, win_obj):
u"""
Выбрать первую запись в гриде. Степ устаревший не рекомендуется к
использованию.
"""
eval_el = find_win_obj(context, win_obj)
context.browser.execute_script("""
(function find_button_into_toolbar(){
'use strict';
var obj = Ext.getCmp('%s');
var grid = obj.items.items[0].selModel.grid;
grid.getSelectionModel().selectFirstRow();
assert(grid.getSelectionModel().hasSelection(), 'Item not selectd');
})()
""" % (eval_el[win_obj]['id']))
@step(u'в окне {win_obj} на вкладке {tab_name} выбрать {one_more}'
u'запись {element} по колонке {column_name}')
@step(u'в окне {win_obj} на вкладке {tab_name} выбрать '
u'запись {element} по колонке {column_name}')
@step(u'в окне {win_obj} на вкладке {tab_name} можно выбрать '
u'запись {element} по колонке {column_name}')
[документация]def step_find_and_select_row_on_tab(context, win_obj, tab_name,
element, column_name, one_more=''):
u"""
Выбор записи в гриде. Степ устаревший, не рекомендуется к использованию.
"""
eval_el = find_win_obj(context, win_obj)
context.browser.execute_script(u"""
ui.find_and_select_row_on_tab('{0}', '{1}', '{2}', '{3}', '{4}')
""".format(
eval_el[win_obj]['id'], tab_name, element, column_name, one_more)
)
@step(u'в окне {win_obj} с одноколоночными гридами '
u'выбрать запись {element} по колонке {column_name}')
def step_find_and_select_row(context, win_obj, element, column_name):
u"""
Выбрать запись в гриде. Степ устаревший, не рекомендуется к использованию.
"""
eval_el = find_win_obj(context, win_obj)
window = context.browser.find_element_by_id(eval_el[win_obj]['id'])
grid_obj = window.find_elements_by_class_name('x-grid-panel')
grid_obj_ids = [str(grid.get_attribute('id')) for grid in grid_obj]
context.browser.execute_script(u"""
ui.find_and_select_row_in_grid({0}, '{1}', '{2}')
""".format(grid_obj_ids, element, column_name))
@step(u'в окне {win_obj} выбрать {one_more} запись {element} по '
u'колонке {column_name}')
@step(u'в окне {win_obj} выбрать запись {element} по колонке {column_name}')
@step(u'в окне {win_obj} можно выбрать запись {element} по '
u'колонке {column_name}')
def step_find_and_select_row(context, win_obj, element, column_name,
one_more=''):
u"""
Степ устаревший, не рекомендуется к использованию.
"""
eval_el = find_win_obj(context, win_obj)
grid_obj = get_toolbar_id_by_column_name(
context, eval_el[win_obj]['id'], column_name
)
if not grid_obj:
grid_obj = ''
context.browser.execute_script(u"""
ui.find_and_select_row('{0}', '{1}', '{2}', '{3}', '{4}')
""".format(eval_el[win_obj]['id'], grid_obj, element,
column_name, one_more)
)
@step(u'в древоводином окне {win_obj} выбрать запись '
u'{elements} по колонке {column_name}')
[документация]def step_find_and_select_node(context, win_obj, elements, column_name):
u"""
Выделяет запись в гриде с древовидной структурой записей. (Например как в
реестре Учреждение на проекте ЭШ).
:param win_obj: Название окна.
:param elements: Имя элемента для выделения. Если элемент является
дочерним, то имя указывается как перечесление всех элементов в пути
разделенных знаком ->. Пример: Министерство -> Управление -> Школа будет
выбран элемент Школа который является дочерним для элемента Управление,
который в свою очередь является дочерним для элемента Министерство.
:param column_name: Столбец для поиска грида.
"""
eval_el = find_win_obj(context, win_obj)
parse_elements = map(lambda x: x.strip(), elements.split('->'))
context.browser.execute_script(u"""
ui.find_and_select_node('{0}', ['{1}'], '{2}')
""".format(eval_el[win_obj]['id'], "', '".join(parse_elements),
column_name))
@step(u'в окне {win_obj} открыть вкладку {tab_name}')
[документация]def step_find_and_open_panel(context, win_obj, tab_name):
u"""
Открывает вкладку с названием tab_name в окне win_obj
:param win_obj: Название окна.
:param tab_name: Название вкладки.
"""
win = get_win_object(context, win_obj)
win.open_tab(tab_name)
@step(u'в Расписании уроков выбрать ячейку на пересечении'
u' класса {class_name} и дня недели {day} со временем {time}')
def step_find_and_select_row(context, class_name, day, time):
u"""
Степ устаревший, не рекомендуется к использованию.
"""
win_obj = u'Расписание уроков'
eval_el = find_win_obj(context, win_obj)
window = context.browser.find_element_by_id(eval_el[win_obj]['id'])
grid_obj = window.find_element_by_class_name('x-grid-panel')
context.browser.execute_script(u"""
ui.find_and_select_row_with_weekday('{0}', '{1}', '{2}', '{3}')
""".format(grid_obj.get_attribute('id'), class_name, day, time))
@step(u'в Классном журнале два раза щелкнуть на ячейку'
u' c датой {date} и временем {time}')
@step(u'в Классном журнале два раза щелкнуть на ячейку'
u' c датой {date} и без времени')
[документация]def step_find_and_select_row(context, date, time=''):
u"""
Вызов Журнала на урок путем двойного щелчка по дате урока.
"""
win_obj = u'Классный журнал'
eval_el = find_win_obj(context, win_obj)
window = context.browser.find_element_by_id(eval_el[win_obj]['id'])
grid_obj = window.find_element_by_class_name('x-grid-panel')
context.browser.execute_script(u"""
ui.find_and_select_row_date('{0}', '{1}', '{2}')
""".format(grid_obj.get_attribute('id'), date, time)
)
@step(u'в окне {win_obj} запись с значением {column_value} по колонке '
u'{column_name} будет удалена')
[документация]def step_is_record_removed(context, win_obj, column_value, column_name):
u"""
Проверка что в гриде нет записи с значение column_value по колонке
column_name. Степ устаревший, не рекомендуется к использованию.
"""
eval_el = find_win_obj(context, win_obj)
toolbar_id = get_toolbar_id_by_column_name(
context, eval_el[win_obj]['id'], column_name
)
record_removed = context.browser.execute_script(u"""
return ui.is_record_removed('{0}', '{1}', '{2}');
""".format(toolbar_id, column_name, column_value))
assert record_removed, "Record not removed"
@step(u'в диалоговом окне {win_obj} нажать кнопку {button_name}')
@step(u'в окне {win_obj} есть безколоночный грид "{grid_name}"')
[документация]def step_find_colmnless_grid(context, win_obj, grid_name):
win_id = find_win_obj(context, win_obj)[win_obj]['id']
grid_list = context.browser.find_elements_by_xpath(
"//div[@id='{0}']"
"//div[contains(@class, 'x-panel x-box-item')]".format(win_id)
)
grid_id = None
for i in xrange(len(grid_list)):
name = grid_list[i].find_element_by_class_name(
'x-panel-header-text').text
if name == grid_name:
grid_id = grid_list[i].get_attribute('id')
context.win_objects['colmnless_grid_id'] = grid_id
break
assert grid_id, 'Columnless grid {0} not found'.format(grid_name)
@step(u'в безколоночном гриде на панели уснструментов есть элемент {element}')
@step(u'в окне "{win_obj}" есть кнопка "{button_name}"')
@step(u'в поле без метки "{field_name}"'
u' окна {win_obj} внести значение {value}')
[документация]def step_set_value(context, field_name, win_obj, value):
u"""
Устанавливает значение value в поле у которого не указан label, например
поле Поиск.
:param win_obj: Название окна.
:param value: Значение для установки в поле.
:param field_name: Значение которое содержится в поле на момент начала
выполнения данного шага..
"""
eval_el = find_win_obj(context, win_obj)
win = context.browser.find_element_by_id(eval_el[win_obj]['id'])
input_field = None
for i in win.find_elements_by_tag_name('input'):
if i.get_attribute('value') == field_name:
input_field = i
break
input_field.clear()
input_field.send_keys(value)
input_field.send_keys(Keys.ENTER)
@step(u'и в окне {win_obj} у поля Поиск нажать кнопку крестик')
[документация]def step_press_clear_trigger(context, win_obj):
u"""
Закрытие окна путем нажатия кнопки "крестик".
"""
eval_el = find_win_obj(context, win_obj)
button = context.browser.find_element_by_xpath(
"//div[@id='{0}']"
"//img[contains(@class, 'x-form-trigger x-form-clear-trigger')]"
"".format(eval_el[win_obj]['id']))
button.click()
@step(u'нажать ENTER в поле со значением {value} окна {win_obj}')
[документация]def step_send_filed(context, value, win_obj):
u"""
Фокусирование на поле с значением value и нажатие кнопки ENTER.
Используется например для заполнения полей поиска.
:param win_obj: Название окна.
:param value: Значение для установки в поле.
"""
eval_el = find_win_obj(context, win_obj)
win = context.browser.find_element_by_id(eval_el[win_obj]['id'])
inputs = win.find_elements_by_tag_name('input')
elem = None
for i in inputs:
if i.get_attribute('value') == value:
elem = i
break
context.action.key_down(Keys.ENTER, elem).perform()
@step(u'в гриде окна {win_obj} кликнуть по заголовку {header_name}')
@step(u'записи в гриде окна {win_obj} будут отсортированы по {sort_type}')
[документация]def step_grid_sort(context, win_obj, sort_type):
u"""
Проверка что в гриде была произведена сортировка.
:param win_obj: Название окна.
:param sort_type: Тип сортировки - по возрастанию или убыванию.
"""
eval_el = find_win_obj(context, win_obj)
window = context.browser.find_element_by_id(eval_el[win_obj]['id'])
grid_obj = window.find_element_by_class_name('x-grid-panel')
sort_info = context.browser.execute_script(u"""
return ui.grid_records_sort_info('{0}')
""".format(grid_obj.get_attribute('id')))
if sort_type == u'возрастанию':
assert sort_info['direction'] == u'ASC'
elif sort_type == u'убыванию':
assert sort_info['direction'] == u'DESC'
@step(u'в окне {win_obj} у поля {field_label} в выпадающем'
u' списке будет значение {element}')
[документация]def ste_find_record_in_m3_select(context, win_obj, field_label, element):
u"""
Проверка того что в выпадающем списке field_label есть значение element.
:param win_obj: Название окна.
:param field_label: Название выпадающего списка.
:param element: Искомое значение.
"""
eval_el = find_win_obj(context, win_obj)
input_id = None
win = context.browser.find_element_by_id(eval_el[win_obj]['id'])
context.webdriverwait.until(
lambda driver: driver.find_element_by_xpath(
"//div[contains(@class, 'x-combo-list-item x-combo-selected')]"
)
)
for i in win.find_elements_by_tag_name('label'):
if field_label in i.text:
input_id = i.get_attribute('for')
break
record_in_list = context.browser.execute_script(u"""
return ui.is_record_in_dynamic_select('{0}','{1}')
""".format(input_id, element))
assert record_in_list, 'Record not in list'
@step(u'в окне {win_obj} отображается кнопка {action} файла')
@step(u'откроется новая вкладка с заголовком {win_title}')
[документация]def step_is_new_tab_open(context, win_title):
u"""
Проверка что открылась новая вкладка браузера.
"""
assert is_tab_with_title_open(context, win_title), "Tab not open"
@step(u'откроется новая вкладка окна {win_obj} с заголовком {tab_name}')
[документация]def step_window_tab_open(context, win_obj, tab_name):
u"""
Проверка что открылась вкладка окна с заголовком tab_name.
"""
win = get_win_object(context, win_obj)
win.open_tab(tab_name)
assert win.is_tab_open(tab_name), "Tab not open"
@step(u'кнопка {button_name} окна "{win_obj}" {status}')
@step(u'ожидаем импорта файла')
[документация]def step_wait_import(context):
u"""
Ожидание завершения импорта файла.
"""
waitForImport(context)
@step(u'в окне {win_obj} содержится сообщение "{message}"')
[документация]def step_message_in_win(context, win_obj, message):
u"""
Проверка того что в окне win_obj отображается сообщение message.
"""
win = get_win_object(context, win_obj)
if win:
text = win.get_text()
else:
win_id = get_modal_win_id_by_name(context, win_obj)
text = context.browser.find_element_by_id(win_id).text
assert message in text, "Text not in window or not match"
@step(u'в html редакторе, окна {win_obj}, с именем {html_name}'
u' ввести значение "{value}"')
def step_set_value_in_html_editor(context, win_obj, html_name, value):
u"""
Установить значение value в редактор типа wysiwyg
"""
win = get_win_object(context, win_obj)
editor = win.get_htmleditor(html_name)
editor.set_value(value)
@step(u'в html редакторе, окна {win_obj}, с именем {html_name}'
u' содержится значение "{value}"')
[документация]def step_set_value_in_html_editor(context, win_obj, html_name, value):
win = get_win_object(context, win_obj)
editor = win.get_htmleditor(html_name)
assert editor.get_value() == value, "Value don't match"
@step(u'в скаченном файле на странице номер {page_num}'
u' содержится запись "{value}"')
@step(u'в скаченном файле содержится запись "{value}"')
[документация]def step_check_record_in_excel(context, value, page_num=1):
u"""
Проверка того что в скаченном Excel файле содержится значение value.
"""
file_name = get_report_file_name(context)
rb = xlrd.open_workbook(context.settings.MEDIA_ROOT + file_name,
formatting_info=True)
sheet = rb.sheet_by_index(int(page_num) - 1)
record_in_file = False
for idx in xrange(0, sheet.nrows):
row = sheet.row_values(idx)
record_in_file = any(value in unicode(r) for r in row)
if record_in_file:
break
assert record_in_file
@step(u'в окне {win_obj} есть безымянное поле с датой {current_date}')
[документация]def step_find_nameless_datefield(context, win_obj, current_date):
date_field = context.browser.find_element_by_name('date')
context.win_objects['nameless_date_field'] = date_field
assert date_field, "Field doesn't exist"
date_field_value = context.browser.execute_script("""
var date_field = Ext.getCmp('{0}');
return date_field.value;
""".format(date_field.get_attribute('id')))
assert current_date == date_field_value, "Dates isn't equal"
@step(u'в окне {win_obj} безымянное поле {field} доступно для редактирования')
[документация]def step_nameless_field_is_edit(context, win_obj, field):
if field == u'даты':
nameless_field = context.win_objects['nameless_date_field']
else:
nameless_field = context.win_objects['nameless_filter_field']
is_edit = context.browser.execute_script("""
var date_field = Ext.getCmp('{0}');
return date_field.isEdit;
""".format(nameless_field.get_attribute('id')))
assert is_edit, "Field isn't editable"
@step(u'в окне {win_obj} есть безымянное поле фильтра со значением "{value}"')
[документация]def step_find_nameless_filter_field(context, win_obj, value):
eval_el = find_win_obj(context, win_obj)
win = context.browser.find_element_by_id(eval_el[win_obj]['id'])
inputs_list = win.find_elements_by_tag_name('input')
exist = None
for i in inputs_list:
if i.get_attribute('value') == value:
exist = True
break
context.win_objects['nameless_filter_field'] = i
assert exist
@step(u'в окне {win_obj} нажать по безымянному полю фильтра')
[документация]def step_click_nameless_filter_field(context, win_obj):
filter_field = context.win_objects['nameless_filter_field']
filter_field.click()
waitForExtAjax(context)
items = context.browser.find_elements_by_css_selector(
".x-combo-list[style*='visibility: visible;'] .x-combo-list-item")
context.win_objects['filter_options'] = items
@step(u'в выпадающем списке будет значение {value}')
[документация]def step_find_value_in_drop_list(context, value):
items = context.win_objects['filter_options']
exist = False
for item in items:
if item.text == value:
exist = True
assert exist
@step(u'в выпадающем списке выбрать пункт "{value}"')
[документация]def step_click_item_in_drop_list(context, value):
items = context.win_objects['filter_options']
option = None
for item in items:
if item.text == value:
option = item
break
assert option, 'Not found option {0}'.format(value)
option.click()
@step(u'зажать кнопку {key_name}')
[документация]def step_hold_key(context, key_name):
keys_dict = {
'CTRL': Keys.CONTROL,
'SHIFT': Keys.SHIFT,
'ALT': Keys.ALT
}
context.action.key_down(keys_dict[key_name]).perform()
@step(u'в окне {win_obj} в странном гриде выбрать запись {value}')
[документация]def step_select_row_in_strange_grid(context, win_obj, value):
win_id = find_win_obj(context, win_obj)[win_obj]['id']
rows_list = context.browser.find_elements_by_xpath(
"//div[@id='{0}']"
"//div[contains(@class, 'x-grid3-cell-inner')]"
"".format(win_id)
)
for row in rows_list:
if row.text == value:
row.click()
break
@step(u'в окне {win_name} есть блок полей с названием {field_set_name}')
[документация]def step_check_fields_set_exists(context, win_name, field_set_name):
u"""
Проверка наличия блока полей с названием field_set_name в окне win_name.
:param win_name: Название окна.
:param field_set_name: Название поля.
"""
win = get_win_object(context, win_name)
assert win.get_fieldset_by_name(field_set_name), (
u"Fieldset name not found.")
@step(u'{action} в окне {win_obj} блок полей {fieldset}')
[документация]def step_open_fieldset(context, action, win_obj, fieldset):
win = get_win_object(context, win_obj)
fs = win.get_fieldset_by_name(fieldset)
fs.click()
@step(u'блок {field_set} окна {win_obj} {collapsed}')
@step(u'блок {field_set} окна "{win_obj}" {collapsed}')
[документация]def step_check_fieldset_is_collapsed(context, field_set, win_obj, collapsed):
win = get_win_object(context, win_obj)
fs = win.get_fieldset_by_name(field_set)
if collapsed == u'свернут':
assert fs.is_collapsed()
else:
assert not fs.is_collapsed()
@step(u'в окне {win_obj} есть поле вильтрации в колонке {col_name}')
[документация]def step_check_filter(context, win_obj, col_name):
column_filter_args = {
u'Учреждение': 'filter_1',
u'Дата': ['filter_2', 'filter_3'],
u'Мероприятие': 'filter_4'
}
win_id = find_win_obj(context, win_obj)[win_obj]['id']
arg_name = column_filter_args[col_name]
if type(arg_name) is list:
for name in arg_name:
filter_field = context.browser.find_element_by_xpath(
"//div[@id='{0}']"
"//input[@name='{1}']".format(win_id, name)
)
assert filter_field
else:
filter_field = context.browser.find_element_by_xpath(
"//div[@id='{0}']"
"//input[@name='{1}']".format(win_id, arg_name)
)
assert filter_field
@step(u'в окне {win_obj} в поле фильтра "{filter_name}"'
u' установить значение {record}')
@step(u'кликнуть по появившемуся выпадающему списку')
[документация]def step_select_current_record_in_select_list(context):
select = context.browser.find_element_by_id(
context.win_objects['editor_id'])
select.click()
@step(u'в {window_title} доступна кнопка {button_name}')
[документация]def step_wait_grid_load(context, window_title, button_name):
u"""
Ждем появления грида путем проверки доступности его кнопки на grid panel.
Используется для ожидания загрузки гридов которые изначально не были на
странице, а подгружаются по наступлению какого-либо события.
(Например журнал для выставление оценок в окне Классный журнал).
"""
win = get_win_object(context, window_title)
context.webdriverwait.until(
lambda driver: driver.find_element_by_xpath(u"""
//div[@id='{win_id}']//button[text()='{b_name}']
""".format(win_id=win.win_id, b_name=button_name))
)
@step(u'в древовидном окне {win_obj} элемент {elements} по колонке'
u' {column_name} не имеет дочерних записей')
[документация]def element_is_leaf(context, win_obj, elements, column_name):
eval_el = find_win_obj(context, win_obj)
context.execute_steps(u'Если в древоводином окне {} '
u'выбрать запись {} '
u'по колонке {}'
u''.format(win_obj, elements, column_name))
is_leaf = context.browser.execute_script(u"""
return ui.element_is_leaf('{}')
""".format(eval_el[win_obj]['id']))
assert is_leaf, 'Element is not a leaf'