diff --git a/.zuul.yaml b/.zuul.yaml index f292f07bc7..822fa1f694 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -26,6 +26,7 @@ - job: name: horizon-selenium-headless parent: horizon-openstack-tox-base + pre-run: playbooks/horizon-selenium-headless/pre.yaml vars: tox_envlist: selenium-headless diff --git a/bindep.txt b/bindep.txt new file mode 100644 index 0000000000..da92738b2c --- /dev/null +++ b/bindep.txt @@ -0,0 +1,5 @@ +# selenium tests +firefox [selenium] +xvfb [selenium platform:dpkg] +# already part of xorg-x11-server on openSUSE +xorg-x11-server-Xvfb [selenium platform:redhat] diff --git a/openstack_dashboard/dashboards/identity/projects/tests.py b/openstack_dashboard/dashboards/identity/projects/tests.py index 3fd6b29f41..6677f808e5 100644 --- a/openstack_dashboard/dashboards/identity/projects/tests.py +++ b/openstack_dashboard/dashboards/identity/projects/tests.py @@ -1318,7 +1318,7 @@ class DetailProjectViewTests(test.BaseAdminViewTests): @tag('selenium') -class SeleniumTests(test.SeleniumAdminTestCase): +class SeleniumTests(test.SeleniumAdminTestCase, test.TestCase): @test.create_mocks({api.keystone: ('get_default_domain', 'get_default_role', 'user_list', diff --git a/openstack_dashboard/dashboards/identity/users/tests.py b/openstack_dashboard/dashboards/identity/users/tests.py index 86a0439da1..2289e6283e 100644 --- a/openstack_dashboard/dashboards/identity/users/tests.py +++ b/openstack_dashboard/dashboards/identity/users/tests.py @@ -993,11 +993,11 @@ class SeleniumTests(test.SeleniumAdminTestCase): if api.keystone.VERSIONS.active >= 3: api.keystone.tenant_list( - IgnoreArg(), domain=None).AndReturn( + IgnoreArg(), False).AndReturn( [self.tenants.list(), False]) else: api.keystone.tenant_list( - IgnoreArg(), user=None).AndReturn( + IgnoreArg(), False).AndReturn( [self.tenants.list(), False]) api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list()) @@ -1011,8 +1011,7 @@ class SeleniumTests(test.SeleniumAdminTestCase): self.selenium.get("%s%s" % (self.live_server_url, USERS_INDEX_URL)) # Open the modal menu - self.selenium.find_element_by_id("users__action_create") \ - .send_keys("\n") + self.selenium.find_element_by_id("users__action_create").click() wait = self.ui.WebDriverWait(self.selenium, 10, ignored_exceptions=[socket_timeout]) wait.until(lambda x: self.selenium.find_element_by_id("id_name")) @@ -1033,7 +1032,7 @@ class SeleniumTests(test.SeleniumAdminTestCase): @test.create_stubs({api.keystone: ('user_get',)}) def test_update_user_with_passwords_not_matching(self): api.keystone.user_get(IsA(http.HttpRequest), '1', - admin=True).AndReturn(self.user) + admin=False).AndReturn(self.user) self.mox.ReplayAll() self.selenium.get("%s%s" % (self.live_server_url, diff --git a/openstack_dashboard/dashboards/project/images/tests.py b/openstack_dashboard/dashboards/project/images/tests.py index afcee9f6c3..8887cc4d68 100644 --- a/openstack_dashboard/dashboards/project/images/tests.py +++ b/openstack_dashboard/dashboards/project/images/tests.py @@ -19,6 +19,7 @@ import os from socket import timeout as socket_timeout +import tempfile import unittest from django import http @@ -376,13 +377,12 @@ class SeleniumTests(test.SeleniumTestCase): driver.get("%s%s" % (self.live_server_url, INDEX_URL)) # Open the modal menu - driver.find_element_by_id("images__action_create").send_keys("\n") + driver.find_element_by_id("images__action_create").click() wait = self.ui.WebDriverWait(self.selenium, 10, ignored_exceptions=[socket_timeout]) wait.until(lambda x: driver.find_element_by_id("id_disk_format")) - srctypes = self.ui.Select(driver.find_element_by_id("id_source_type")) - srctypes.select_by_value("url") + driver.find_element_by_xpath('//a[@data-select-value="url"]').click() copyfrom = driver.find_element_by_id("id_image_url") copyfrom.send_keys("http://www.test.com/test.iso") formats = self.ui.Select(driver.find_element_by_id("id_disk_format")) @@ -412,15 +412,16 @@ class SeleniumTests(test.SeleniumTestCase): driver.get("%s%s" % (self.live_server_url, INDEX_URL)) # Open the modal menu - driver.find_element_by_id("images__action_create").send_keys("\n") + driver.find_element_by_id("images__action_create").click() wait = self.ui.WebDriverWait(driver, 10, ignored_exceptions=[socket_timeout]) wait.until(lambda x: driver.find_element_by_id("id_disk_format")) - srctypes = self.ui.Select(driver.find_element_by_id("id_source_type")) - srctypes.select_by_value("file") - driver.find_element_by_id("id_image_file").send_keys("/tmp/test.iso") + driver.find_element_by_xpath('//a[@data-select-value="file"]').click() + with tempfile.NamedTemporaryFile() as tmp: + driver.find_element_by_id("id_image_file").send_keys(tmp.name) formats = self.ui.Select(driver.find_element_by_id("id_disk_format")) + formats.select_by_visible_text('ISO - Optical Disk Image') body = formats.first_selected_option self.assertIn("ISO", body.text, "ISO should be selected when the extension is *.iso") @@ -443,11 +444,11 @@ class SeleniumTests(test.SeleniumTestCase): ignored_exceptions=[socket_timeout]) wait.until(lambda x: driver.find_element_by_id("id_disk_format")) - srctypes = self.ui.Select(driver.find_element_by_id("id_source_type")) - srctypes.select_by_value("url") + driver.find_element_by_xpath('//a[@data-select-value="url"]').click() copyfrom = driver.find_element_by_id("id_image_url") copyfrom.send_keys("http://www.test.com/test.iso") formats = self.ui.Select(driver.find_element_by_id("id_disk_format")) + formats.select_by_visible_text('ISO - Optical Disk Image') body = formats.first_selected_option self.assertIn("ISO", body.text, "ISO should be selected when the extension is *.iso") @@ -472,10 +473,12 @@ class SeleniumTests(test.SeleniumTestCase): ignored_exceptions=[socket_timeout]) wait.until(lambda x: driver.find_element_by_id("id_disk_format")) - srctypes = self.ui.Select(driver.find_element_by_id("id_source_type")) - srctypes.select_by_value("file") - driver.find_element_by_id("id_image_file").send_keys("/tmp/test.iso") + driver.find_element_by_xpath('//a[@data-select-value="file"]').click() + with tempfile.NamedTemporaryFile() as tmp: + driver.find_element_by_id("id_image_file").send_keys(tmp.name) formats = self.ui.Select(driver.find_element_by_id("id_disk_format")) + formats.select_by_visible_text('ISO - Optical Disk Image') body = formats.first_selected_option + self.assertIn("ISO", body.text, "ISO should be selected when the extension is *.iso") diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py index d0cfc0424b..bd34eb12e8 100644 --- a/openstack_dashboard/test/settings.py +++ b/openstack_dashboard/test/settings.py @@ -134,6 +134,7 @@ settings_utils.find_static_files(HORIZON_CONFIG, AVAILABLE_THEMES, # image form. If set to 'off', there will be no file form field on the create # image form. See documentation for deployment considerations. HORIZON_IMAGES_UPLOAD_MODE = 'legacy' +IMAGES_ALLOW_LOCATION = True AVAILABLE_REGIONS = [ ('http://localhost:5000/v3', 'local'), diff --git a/playbooks/horizon-selenium-headless/pre.yaml b/playbooks/horizon-selenium-headless/pre.yaml new file mode 100644 index 0000000000..fe883fe4f3 --- /dev/null +++ b/playbooks/horizon-selenium-headless/pre.yaml @@ -0,0 +1,7 @@ +--- +- hosts: all + roles: + - role: bindep + bindep_profile: selenium + become: true + - setup-selenium-tests diff --git a/roles/setup-selenium-tests/defaults/main.yaml b/roles/setup-selenium-tests/defaults/main.yaml new file mode 100644 index 0000000000..ee6d28c294 --- /dev/null +++ b/roles/setup-selenium-tests/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +geckodriver_url: "https://github.com/mozilla/geckodriver/releases/download/v0.19.1/geckodriver-v0.19.1-linux64.tar.gz" diff --git a/roles/setup-selenium-tests/tasks/main.yaml b/roles/setup-selenium-tests/tasks/main.yaml new file mode 100644 index 0000000000..5e1145bbff --- /dev/null +++ b/roles/setup-selenium-tests/tasks/main.yaml @@ -0,0 +1,13 @@ +--- +- name: download the Gecko WebDriver + get_url: + url: "{{ geckodriver_url }}" + dest: "/tmp/geckodriver.package" + +- name: extract the Gecko WebDriver + become: true + unarchive: + src: "/tmp/geckodriver.package" + dest: "/usr/local/bin" + remote_src: yes +