[tests] refactored live server tests to prevent race conditions
parent
868c54212f
commit
b8bf183ba9
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
import time
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.urls import reverse
|
||||
|
|
@ -10,17 +11,87 @@ from selenium.webdriver.support.ui import Select
|
|||
from ..management.commands.createtestdata import create_test_data
|
||||
|
||||
|
||||
class FilterPage:
|
||||
WAIT_FOR_RELOAD = 1
|
||||
URL_PATH = reverse('admin:testapp_modela_changelist')
|
||||
|
||||
# ul-indexes
|
||||
MULTISELECT_UL = 3
|
||||
MULTISELECT_RELATED_UL = 7
|
||||
|
||||
def __init__(self, selenium, base_url):
|
||||
self.base_url = base_url
|
||||
self.url = base_url + self.URL_PATH
|
||||
self.selenium = selenium
|
||||
self.current_url = self.selenium.current_url
|
||||
|
||||
def login(self, client):
|
||||
# login to selenium - using a cookie from the django test client
|
||||
admin = User.objects.get(username='admin')
|
||||
client.force_login(admin)
|
||||
cookie = client.cookies['sessionid']
|
||||
#selenium will set cookie domain based on current page domain
|
||||
self.selenium.get(self.base_url + '/admin/')
|
||||
self.selenium.add_cookie({'name': 'sessionid', 'value': cookie.value, 'secure': False, 'path': '/'})
|
||||
#need to update page for logged in user
|
||||
self.selenium.refresh()
|
||||
|
||||
def get(self, url_query=str()):
|
||||
return self.selenium.get(self.url + '?' + url_query)
|
||||
|
||||
def wait_for_reload(self):
|
||||
now = time.time()
|
||||
while self.current_url == self.selenium.current_url:
|
||||
self.selenium.refresh()
|
||||
if time.time() - now < self.WAIT_FOR_RELOAD:
|
||||
msg = "Could not reload live server page. Waited {} sec."
|
||||
raise RuntimeError(msg.format(self.WAIT_FOR_RELOAD))
|
||||
else:
|
||||
self.current_url = self.selenium.current_url
|
||||
return True
|
||||
|
||||
@property
|
||||
def item_count(self):
|
||||
return len(self.selenium.find_elements_by_xpath('//*[@id="result_list"]/tbody/tr'))
|
||||
|
||||
@property
|
||||
def url_query(self):
|
||||
return self.selenium.current_url.split('?')[-1].replace('%2C', ',')
|
||||
|
||||
def get_selected_li_count(self, ul):
|
||||
return len(ul.find_elements_by_css_selector('li.selected'))
|
||||
|
||||
def use_dropdown_filter(self, select_id, option):
|
||||
select = Select(self.selenium.find_element_by_id(select_id))
|
||||
select.select_by_visible_text(option)
|
||||
self.wait_for_reload()
|
||||
return Select(self.selenium.find_element_by_id(select_id))
|
||||
|
||||
def use_multiselect_filter(self, ul_num, title):
|
||||
ul_xpath = '//*[@id="changelist-filter"]/ul[{}]'.format(ul_num)
|
||||
a_css = 'li a[title="{}"]'.format(title)
|
||||
ul = self.selenium.find_element_by_xpath(ul_xpath)
|
||||
ul.find_element_by_css_selector(a_css).click()
|
||||
self.wait_for_reload()
|
||||
return self.selenium.find_element_by_xpath(ul_xpath)
|
||||
|
||||
def use_multiselect_dropdown_filter(self, field, options):
|
||||
select = Select(self.selenium.find_element_by_id(field + '_select'))
|
||||
for value in options:
|
||||
select.select_by_value(value)
|
||||
self.selenium.find_element_by_id(field + '_submit').click()
|
||||
self.wait_for_reload()
|
||||
return Select(self.selenium.find_element_by_id(field + '_select'))
|
||||
|
||||
|
||||
class LiveFilterTest(StaticLiveServerTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
options = Options()
|
||||
options.headless = True
|
||||
cls.selenium = WebDriver(options=options)
|
||||
cls.selenium.implicitly_wait(10)
|
||||
cls.url_path = reverse('admin:testapp_modela_changelist')
|
||||
create_test_data()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
|
@ -28,105 +99,82 @@ class LiveFilterTest(StaticLiveServerTestCase):
|
|||
super().tearDownClass()
|
||||
|
||||
def setUp(self):
|
||||
# login to selenium - using a cookie from the django test client
|
||||
admin = User.objects.get(username='admin')
|
||||
self.client.force_login(admin)
|
||||
cookie = self.client.cookies['sessionid']
|
||||
self.selenium.get(self.live_server_url + '/admin/') #selenium will set cookie domain based on current page domain
|
||||
self.selenium.add_cookie({'name': 'sessionid', 'value': cookie.value, 'secure': False, 'path': '/'})
|
||||
self.selenium.refresh() #need to update page for logged in user
|
||||
create_test_data()
|
||||
self.page = FilterPage(self.selenium, self.live_server_url)
|
||||
self.page.login(self.client)
|
||||
|
||||
def get_item_count(self):
|
||||
return len(self.selenium.find_elements_by_xpath('//*[@id="result_list"]/tbody/tr'))
|
||||
|
||||
def get_url_query(self):
|
||||
return self.selenium.current_url.split('?')[-1].replace('%2C', ',')
|
||||
|
||||
def get_selected_list_items(self, ul_num):
|
||||
xpath = '//*[@id="changelist-filter"]/ul[{}]/li[@class="selected"]'.format(ul_num)
|
||||
return self.selenium.find_elements_by_xpath(xpath)
|
||||
|
||||
def use_dropdown_filter(self, select_id, option, url_query, item_count):
|
||||
select = Select(self.selenium.find_element_by_id(select_id))
|
||||
select.select_by_visible_text(option)
|
||||
self.selenium.refresh()
|
||||
select = Select(self.selenium.find_element_by_id(select_id))
|
||||
self.assertEqual(self.get_item_count(), item_count)
|
||||
self.assertEqual(self.get_url_query(), url_query)
|
||||
def check_dropdown_filter(self, select_id, query_key, query_value, option, count):
|
||||
select = self.page.use_dropdown_filter(select_id, option)
|
||||
self.assertEqual(self.page.item_count, count)
|
||||
self.assertEqual(select.first_selected_option.text, option)
|
||||
if option == 'All':
|
||||
self.assertNotIn(query_key, self.page.url_query)
|
||||
else:
|
||||
self.assertIn(query_key + query_value, self.page.url_query)
|
||||
|
||||
def use_multiselect_link(self, ul_num, title, item_count, selected_count, url_query):
|
||||
link = '//*[@id="changelist-filter"]/ul[{}]/li/a[@title="{}"]'.format(ul_num, title)
|
||||
self.selenium.find_element_by_xpath(link).click()
|
||||
self.selenium.refresh()
|
||||
self.assertIn(url_query, self.get_url_query())
|
||||
self.assertEqual(self.get_item_count(), item_count)
|
||||
self.assertEqual(len(self.get_selected_list_items(ul_num)), selected_count)
|
||||
def test_01_dropdown_filter(self):
|
||||
self.page.get()
|
||||
|
||||
def use_multiselect_dropdown_filter(self, field, options, url_param, count):
|
||||
select = Select(self.selenium.find_element_by_id(field + '_select'))
|
||||
for value in options:
|
||||
select.select_by_value(value)
|
||||
self.selenium.find_element_by_id(field + '_submit').click()
|
||||
self.selenium.refresh()
|
||||
select = Select(self.selenium.find_element_by_id(field + '_select'))
|
||||
self.assertIn(url_param + '=' + ','.join(options), self.get_url_query())
|
||||
self.assertEqual(len(select.all_selected_options), len(options))
|
||||
self.assertEqual(self.get_item_count(), count)
|
||||
select.deselect_all()
|
||||
# check simple dropdown filter
|
||||
select_id, query_key = 'dropdown-gt3_filter_select', 'dropdown_gt3='
|
||||
self.check_dropdown_filter(select_id, query_key, '2', '2', 9)
|
||||
self.check_dropdown_filter(select_id, query_key, '', 'All', 36)
|
||||
|
||||
def test_01_check_filter(self):
|
||||
self.selenium.get(self.live_server_url + self.url_path)
|
||||
# Check choices dropdown filter:
|
||||
select_id, query_key = 'choices-dropdown_filter_select', 'choices_dropdown__exact='
|
||||
self.check_dropdown_filter(select_id, query_key, '3', 'three', 4)
|
||||
self.check_dropdown_filter(select_id, query_key, '', 'All', 36)
|
||||
|
||||
# Check the simple dropdown filter:
|
||||
select_id = 'dropdown-gt3_filter_select'
|
||||
url_query = 'dropdown_gt3=2'
|
||||
self.use_dropdown_filter(select_id, '2', url_query, 9)
|
||||
self.use_dropdown_filter(select_id, 'All', '', 36)
|
||||
# Check related dropdown filter:
|
||||
select_id, query_key = 'related-dropdown_filter_select', 'related_dropdown__id__exact='
|
||||
self.check_dropdown_filter(select_id, query_key, '9', 'ModelB 9', 1)
|
||||
self.check_dropdown_filter(select_id, query_key, '', 'All', 36)
|
||||
|
||||
# Check the choices dropdown filter:
|
||||
select_id = 'choices-dropdown_filter_select'
|
||||
url_query = 'choices_dropdown__exact=3'
|
||||
self.use_dropdown_filter(select_id, 'three', url_query, 4)
|
||||
self.use_dropdown_filter(select_id, 'All', '', 36)
|
||||
def check_multiselect_filter(self, ul_num, query_key, query_value, option, count, selected):
|
||||
ul = self.page.use_multiselect_filter(ul_num, option)
|
||||
self.assertEqual(self.page.item_count, count)
|
||||
self.assertEqual(self.page.get_selected_li_count(ul), selected)
|
||||
if option == 'All':
|
||||
self.assertNotIn(query_key, self.page.url_query)
|
||||
else:
|
||||
self.assertIn(query_key + query_value, self.page.url_query)
|
||||
|
||||
# # Check the related dropdown filter:
|
||||
select_id = 'related-dropdown_filter_select'
|
||||
url_query = 'related_dropdown__id__exact=9'
|
||||
self.use_dropdown_filter(select_id, 'ModelB 9', url_query, 1)
|
||||
self.use_dropdown_filter(select_id, 'All', '', 36)
|
||||
def test_02_multiselect_filter(self):
|
||||
# start with an already filtered changelist
|
||||
self.page.get('dropdown_gt3=2')
|
||||
|
||||
# Start tests with activated dropdown_gt3 filter
|
||||
self.selenium.get(self.live_server_url + self.url_path + '?dropdown_gt3=2')
|
||||
|
||||
# Check the simple multiselect filter
|
||||
self.use_multiselect_link(3, '4', 2, 1, 'multiselect__in=4')
|
||||
self.use_multiselect_link(3, '3', 3, 2, 'multiselect__in=4,3')
|
||||
self.use_multiselect_link(3, '2', 5, 3, 'multiselect__in=4,3,2')
|
||||
self.use_multiselect_link(3, '3', 4, 2, 'multiselect__in=4,2')
|
||||
self.use_multiselect_link(3, 'All', 9, 1, '')
|
||||
self.assertNotIn('multiselect__in', self.get_url_query())
|
||||
# check simple multiselect filter
|
||||
ul_num, query_key = self.page.MULTISELECT_UL, 'multiselect__in='
|
||||
self.check_multiselect_filter(ul_num, query_key, '4', '4', 2, 1)
|
||||
self.check_multiselect_filter(ul_num, query_key, '4,3', '3', 3, 2)
|
||||
self.check_multiselect_filter(ul_num, query_key, '4,3,2', '2', 5, 3)
|
||||
self.check_multiselect_filter(ul_num, query_key, '', 'All', 9, 1)
|
||||
|
||||
# check the multiselect related filter
|
||||
self.use_multiselect_link(7, 'ModelB 34', 1, 1, 'multiselect_related__id__in=34')
|
||||
self.use_multiselect_link(7, 'ModelB 30', 2, 2, 'multiselect_related__id__in=34,30')
|
||||
self.use_multiselect_link(7, 'ModelB 26', 3, 3, 'multiselect_related__id__in=34,30,26')
|
||||
self.use_multiselect_link(7, 'ModelB 34', 2, 2, 'multiselect_related__id__in=30,26')
|
||||
self.use_multiselect_link(7, 'All', 9, 1, '')
|
||||
self.assertNotIn('multiselect_related__id__in', self.get_url_query())
|
||||
ul_num, query_key = self.page.MULTISELECT_RELATED_UL, 'multiselect_related__id__in='
|
||||
self.check_multiselect_filter(ul_num, query_key, '34', 'ModelB 34', 1, 1)
|
||||
self.check_multiselect_filter(ul_num, query_key, '34,30', 'ModelB 30', 2, 2)
|
||||
self.check_multiselect_filter(ul_num, query_key, '34,30,26', 'ModelB 26', 3, 3)
|
||||
self.check_multiselect_filter(ul_num, query_key, '30,26', 'ModelB 34', 2, 2)
|
||||
self.check_multiselect_filter(ul_num, query_key, '', 'All', 9, 1)
|
||||
|
||||
# Start tests without any filter.
|
||||
self.selenium.get(self.live_server_url + self.url_path)
|
||||
def check_multiselect_dropdown_filter(self, field, options, query_key, count):
|
||||
select = self.page.use_multiselect_dropdown_filter(field, options)
|
||||
self.assertEqual(len(select.all_selected_options), len(options))
|
||||
self.assertEqual(self.page.item_count, count)
|
||||
self.assertIn(query_key + ','.join(options), self.page.url_query)
|
||||
select.deselect_all()
|
||||
|
||||
def test_03_multiselect_dropdown_filter(self):
|
||||
self.page.get()
|
||||
|
||||
# check multiselect-dropdown
|
||||
field = 'multiselect-dropdown'
|
||||
url_param = 'multiselect_dropdown__in'
|
||||
field, query_key = 'multiselect-dropdown', 'multiselect_dropdown__in='
|
||||
options = [str(i) for i in range(2, 5)]
|
||||
self.use_multiselect_dropdown_filter(field, options, url_param, 18)
|
||||
self.check_multiselect_dropdown_filter(field, options, query_key, 18)
|
||||
|
||||
# check multiselect-related-dropdown
|
||||
# (multiselect-dropdown filter is still effectual)
|
||||
field = 'multiselect-related-dropdown'
|
||||
url_param = 'multiselect_related_dropdown__id__in'
|
||||
field, query_key = 'multiselect-related-dropdown', 'multiselect_related_dropdown__id__in='
|
||||
options = [str(i) for i in range(1, 9)]
|
||||
self.use_multiselect_dropdown_filter(field, options, url_param, 4)
|
||||
self.check_multiselect_dropdown_filter(field, options, query_key, 4)
|
||||
|
|
|
|||
Loading…
Reference in New Issue