Fixed/enabled selenium tests.
Moved the tests to the horizon portion since they test core functionality. This also required moving some of the templates, etc. that belong in horizon to their proper homes. Change-Id: I7d9758845b81e4b8bcf1ffaaff4f6e237b4fe9f8
This commit is contained in:
parent
6c766326b5
commit
6f838a09b8
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
@ -30,10 +30,12 @@ from django.contrib.messages.storage import default_storage
|
|||||||
from django.contrib.auth.middleware import AuthenticationMiddleware
|
from django.contrib.auth.middleware import AuthenticationMiddleware
|
||||||
from django.core.handlers import wsgi
|
from django.core.handlers import wsgi
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
|
from django.utils import unittest
|
||||||
|
|
||||||
from glanceclient.v1 import client as glance_client
|
from glanceclient.v1 import client as glance_client
|
||||||
from keystoneclient.v2_0 import client as keystone_client
|
from keystoneclient.v2_0 import client as keystone_client
|
||||||
from novaclient.v1_1 import client as nova_client
|
from novaclient.v1_1 import client as nova_client
|
||||||
|
from selenium.webdriver.firefox.webdriver import WebDriver
|
||||||
|
|
||||||
import httplib2
|
import httplib2
|
||||||
import mox
|
import mox
|
||||||
@ -325,3 +327,19 @@ class APITestCase(TestCase):
|
|||||||
.AndReturn(self.swiftclient)
|
.AndReturn(self.swiftclient)
|
||||||
expected_calls -= 1
|
expected_calls -= 1
|
||||||
return self.swiftclient
|
return self.swiftclient
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(os.environ.get('WITH_SELENIUM', False),
|
||||||
|
"The WITH_SELENIUM env variable is not set.")
|
||||||
|
class SeleniumTestCase(django_test.LiveServerTestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
if os.environ.get('WITH_SELENIUM', False):
|
||||||
|
cls.selenium = WebDriver()
|
||||||
|
super(SeleniumTestCase, cls).setUpClass()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
super(SeleniumTestCase, cls).tearDownClass()
|
||||||
|
if os.environ.get('WITH_SELENIUM', False):
|
||||||
|
cls.selenium.quit()
|
||||||
|
@ -49,14 +49,14 @@ class MyPanel(horizon.Panel):
|
|||||||
name = _("My Panel")
|
name = _("My Panel")
|
||||||
slug = "myslug"
|
slug = "myslug"
|
||||||
permissions = ("openstack.services.compute",)
|
permissions = ("openstack.services.compute",)
|
||||||
urls = 'horizon.tests.test_panel_urls'
|
urls = 'horizon.tests.test_dashboards.cats.kittens.urls'
|
||||||
|
|
||||||
|
|
||||||
class AdminPanel(horizon.Panel):
|
class AdminPanel(horizon.Panel):
|
||||||
name = _("Admin Panel")
|
name = _("Admin Panel")
|
||||||
slug = "admin_panel"
|
slug = "admin_panel"
|
||||||
permissions = ("openstack.roles.admin",)
|
permissions = ("openstack.roles.admin",)
|
||||||
urls = 'horizon.tests.test_panel_urls'
|
urls = 'horizon.tests.test_dashboards.cats.kittens.urls'
|
||||||
|
|
||||||
|
|
||||||
class BaseHorizonTests(test.TestCase):
|
class BaseHorizonTests(test.TestCase):
|
||||||
@ -256,6 +256,13 @@ class HorizonTests(BaseHorizonTests):
|
|||||||
panel = dash.get_panel('myslug')
|
panel = dash.get_panel('myslug')
|
||||||
self._reload_urls()
|
self._reload_urls()
|
||||||
|
|
||||||
|
# Set roles for admin user
|
||||||
|
self.setActiveUser(token=self.token,
|
||||||
|
username=self.user.name,
|
||||||
|
tenant_id=self.tenant.id,
|
||||||
|
service_catalog=self.request.user.service_catalog,
|
||||||
|
roles=[{'name': 'admin'}])
|
||||||
|
|
||||||
# With the required service, the page returns fine.
|
# With the required service, the page returns fine.
|
||||||
resp = self.client.get(panel.get_absolute_url())
|
resp = self.client.get(panel.get_absolute_url())
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
38
horizon/tests/selenium_tests.py
Normal file
38
horizon/tests/selenium_tests.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2012 Nebula, 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 horizon import test
|
||||||
|
|
||||||
|
import selenium.webdriver.support.ui as ui
|
||||||
|
|
||||||
|
|
||||||
|
class BrowserTests(test.SeleniumTestCase):
|
||||||
|
def test_splash(self):
|
||||||
|
self.selenium.get(self.live_server_url)
|
||||||
|
button = self.selenium.find_element_by_tag_name("button")
|
||||||
|
self.assertEqual(button.text, "Sign In")
|
||||||
|
|
||||||
|
def test_qunit(self):
|
||||||
|
self.selenium.get("%s%s" % (self.live_server_url, "/qunit/"))
|
||||||
|
wait = ui.WebDriverWait(self.selenium, 10)
|
||||||
|
|
||||||
|
def qunit_done(driver):
|
||||||
|
text = driver.find_element_by_id("qunit-testresult").text
|
||||||
|
return "Tests completed" in text
|
||||||
|
|
||||||
|
wait.until(qunit_done)
|
||||||
|
failed = self.selenium.find_element_by_class_name("failed")
|
||||||
|
self.assertEqual(int(failed.text), 0)
|
@ -1,34 +0,0 @@
|
|||||||
{% load branding i18n %}
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
|
|
||||||
<title>{% block title %}{% endblock %} - {% site_branding %}</title>
|
|
||||||
{% include "horizon/_conf.html" %}
|
|
||||||
{% include "horizon/client_side/_script_loader.html" %}
|
|
||||||
</head>
|
|
||||||
<body id="{% block body_id %}{% endblock %}">
|
|
||||||
{% block content %}
|
|
||||||
<div id="container">
|
|
||||||
{% block sidebar %}
|
|
||||||
{% include 'horizon/common/_sidebar.html' %}
|
|
||||||
{% endblock %}
|
|
||||||
<div id='main_content'>
|
|
||||||
<div class='topbar'>
|
|
||||||
{% include "_header.html" %}
|
|
||||||
{% block page_header %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
{% include "horizon/_messages.html" %}
|
|
||||||
{% block main %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
<div id="footer">
|
|
||||||
{% block footer %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
{% block js %}
|
|
||||||
{% include "horizon/_scripts.html" %}
|
|
||||||
{% endblock %}
|
|
||||||
<div id="modal_wrapper" />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,21 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright 2011 Nebula, 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 django.conf.urls.defaults import *
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
|
||||||
url(r'^$', 'horizon.tests.views.fakeView', name='index'),
|
|
||||||
)
|
|
@ -44,10 +44,12 @@ DEFAULT_EXCEPTION_REPORTER_FILTER = 'horizon.exceptions.HorizonReporterFilter'
|
|||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.humanize',
|
'django.contrib.humanize',
|
||||||
'django_nose',
|
'django_nose',
|
||||||
'openstack_auth',
|
'openstack_auth',
|
||||||
|
'compressor',
|
||||||
'horizon',
|
'horizon',
|
||||||
'horizon.tests',
|
'horizon.tests',
|
||||||
'horizon.dashboards.nova',
|
'horizon.dashboards.nova',
|
||||||
@ -116,6 +118,16 @@ HORIZON_CONFIG = {
|
|||||||
'user_home': None
|
'user_home': None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMPRESS_ENABLED = False
|
||||||
|
COMPRESS_OFFLINE = False
|
||||||
|
COMPRESS_ROOT = "/tmp/"
|
||||||
|
|
||||||
|
STATICFILES_FINDERS = (
|
||||||
|
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||||
|
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||||
|
'compressor.finders.CompressorFinder',
|
||||||
|
)
|
||||||
|
|
||||||
AVAILABLE_REGIONS = [
|
AVAILABLE_REGIONS = [
|
||||||
('http://localhost:5000/v2.0', 'local'),
|
('http://localhost:5000/v2.0', 'local'),
|
||||||
('http://remote:5000/v2.0', 'remote'),
|
('http://remote:5000/v2.0', 'remote'),
|
||||||
|
@ -23,12 +23,19 @@ URL patterns for testing Horizon views.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf.urls.defaults import patterns, url, include
|
from django.conf.urls.defaults import patterns, url, include
|
||||||
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||||
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^$', 'horizon.tests.views.fakeView', name='splash'),
|
url(r'^$', 'horizon.views.splash', name='splash'),
|
||||||
url(r'^auth/', include('openstack_auth.urls')),
|
url(r'^auth/', include('openstack_auth.urls')),
|
||||||
url(r'', include(horizon.urls)),
|
url(r'', include(horizon.urls)),
|
||||||
|
url(r'^qunit/$',
|
||||||
|
TemplateView.as_view(template_name="horizon/qunit.html"),
|
||||||
|
name='qunit_tests')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
urlpatterns += staticfiles_urlpatterns()
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright 2012 United States Government as represented by the
|
|
||||||
# Administrator of the National Aeronautics and Space Administration.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Copyright 2012 Nebula, 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 django import http
|
|
||||||
|
|
||||||
|
|
||||||
def fakeView(request):
|
|
||||||
resp = http.HttpResponse()
|
|
||||||
resp.write('<html><body><p>'
|
|
||||||
'This is a fake httpresponse from a fake view for testing '
|
|
||||||
' purposes only'
|
|
||||||
'</p></body></html>')
|
|
||||||
return resp
|
|
@ -14,4 +14,4 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from .base import APIView, user_home
|
from .base import APIView, user_home, splash
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
from django import shortcuts
|
from django import shortcuts
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
|
from django.views.decorators import vary
|
||||||
|
|
||||||
|
from openstack_auth.views import Login
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
from horizon import exceptions
|
from horizon import exceptions
|
||||||
@ -26,6 +29,22 @@ def user_home(request):
|
|||||||
return shortcuts.redirect(horizon.get_user_home(request.user))
|
return shortcuts.redirect(horizon.get_user_home(request.user))
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_home(user):
|
||||||
|
if user.is_superuser:
|
||||||
|
return horizon.get_dashboard('syspanel').get_absolute_url()
|
||||||
|
return horizon.get_dashboard('nova').get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
@vary.vary_on_cookie
|
||||||
|
def splash(request):
|
||||||
|
if request.user.is_authenticated():
|
||||||
|
return shortcuts.redirect(get_user_home(request.user))
|
||||||
|
form = Login(request)
|
||||||
|
request.session.clear()
|
||||||
|
request.session.set_test_cookie()
|
||||||
|
return shortcuts.render(request, 'splash.html', {'form': form})
|
||||||
|
|
||||||
|
|
||||||
class APIView(generic.TemplateView):
|
class APIView(generic.TemplateView):
|
||||||
""" A quick class-based view for putting API data into a template.
|
""" A quick class-based view for putting API data into a template.
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ ROOT_URLCONF = 'openstack_dashboard.urls'
|
|||||||
HORIZON_CONFIG = {
|
HORIZON_CONFIG = {
|
||||||
'dashboards': ('nova', 'syspanel', 'settings',),
|
'dashboards': ('nova', 'syspanel', 'settings',),
|
||||||
'default_dashboard': 'nova',
|
'default_dashboard': 'nova',
|
||||||
'user_home': 'openstack_dashboard.views.user_home',
|
'user_home': 'horizon.views.user_home',
|
||||||
'ajax_queue_limit': 10
|
'ajax_queue_limit': 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import "../../bootstrap/less/bootstrap.less";
|
@import "../../../../horizon/static/bootstrap/less/bootstrap.less";
|
||||||
|
|
||||||
/* new clearfix */
|
/* new clearfix */
|
||||||
.clearfix:after {
|
.clearfix:after {
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
from django import test
|
|
||||||
from django.utils import unittest
|
|
||||||
|
|
||||||
from selenium.webdriver.firefox.webdriver import WebDriver
|
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(os.environ.get('WITH_SELENIUM', False),
|
|
||||||
"The WITH_SELENIUM env variable is not set.")
|
|
||||||
class SeleniumTests(test.LiveServerTestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
if os.environ.get('WITH_SELENIUM', False):
|
|
||||||
cls.selenium = WebDriver()
|
|
||||||
super(SeleniumTests, cls).setUpClass()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
super(SeleniumTests, cls).tearDownClass()
|
|
||||||
if os.environ.get('WITH_SELENIUM', False):
|
|
||||||
cls.selenium.quit()
|
|
||||||
|
|
||||||
def test_splash(self):
|
|
||||||
self.selenium.get(self.live_server_url)
|
|
||||||
button = self.selenium.find_element_by_tag_name("button")
|
|
||||||
self.assertEqual(button.text, "Sign In")
|
|
||||||
|
|
||||||
def test_qunit(self):
|
|
||||||
self.selenium.get("%s%s" % (self.live_server_url, "/qunit/")),
|
|
||||||
self.selenium.implicitly_wait("1000")
|
|
||||||
failed = self.selenium.find_element_by_class_name("failed")
|
|
||||||
self.assertEqual(int(failed.text), 0)
|
|
@ -31,7 +31,7 @@ import horizon
|
|||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^$', 'openstack_dashboard.views.splash', name='splash'),
|
url(r'^$', 'horizon.views.splash', name='splash'),
|
||||||
url(r'^auth/', include('openstack_auth.urls')),
|
url(r'^auth/', include('openstack_auth.urls')),
|
||||||
url(r'', include(horizon.urls)))
|
url(r'', include(horizon.urls)))
|
||||||
|
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright 2012 United States Government as represented by the
|
|
||||||
# Administrator of the National Aeronautics and Space Administration.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Copyright 2012 Nebula, 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.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Views for home page.
|
|
||||||
"""
|
|
||||||
from django import shortcuts
|
|
||||||
from django.views.decorators import vary
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
from openstack_auth.views import Login
|
|
||||||
|
|
||||||
|
|
||||||
def user_home(user):
|
|
||||||
if user.is_superuser:
|
|
||||||
return horizon.get_dashboard('syspanel').get_absolute_url()
|
|
||||||
return horizon.get_dashboard('nova').get_absolute_url()
|
|
||||||
|
|
||||||
|
|
||||||
@vary.vary_on_cookie
|
|
||||||
def splash(request):
|
|
||||||
if request.user.is_authenticated():
|
|
||||||
return shortcuts.redirect(user_home(request.user))
|
|
||||||
form = Login(request)
|
|
||||||
request.session.clear()
|
|
||||||
request.session.set_test_cookie()
|
|
||||||
return shortcuts.render(request, 'splash.html', {'form': form})
|
|
@ -259,6 +259,10 @@ function install_venv {
|
|||||||
function run_tests {
|
function run_tests {
|
||||||
sanity_check
|
sanity_check
|
||||||
|
|
||||||
|
if [ $selenium -eq 1 ]; then
|
||||||
|
export WITH_SELENIUM=1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Running Horizon application tests"
|
echo "Running Horizon application tests"
|
||||||
export NOSE_XUNIT_FILE=horizon/nosetests.xml
|
export NOSE_XUNIT_FILE=horizon/nosetests.xml
|
||||||
${command_wrapper} coverage erase
|
${command_wrapper} coverage erase
|
||||||
@ -267,9 +271,6 @@ function run_tests {
|
|||||||
HORIZON_RESULT=$?
|
HORIZON_RESULT=$?
|
||||||
|
|
||||||
echo "Running openstack_dashboard tests"
|
echo "Running openstack_dashboard tests"
|
||||||
if [ $selenium -eq 1 ]; then
|
|
||||||
export WITH_SELENIUM=1
|
|
||||||
fi
|
|
||||||
export NOSE_XUNIT_FILE=openstack_dashboard/nosetests.xml
|
export NOSE_XUNIT_FILE=openstack_dashboard/nosetests.xml
|
||||||
${command_wrapper} coverage run -p $root/manage.py test openstack_dashboard --settings=openstack_dashboard.test.settings $testargs
|
${command_wrapper} coverage run -p $root/manage.py test openstack_dashboard --settings=openstack_dashboard.test.settings $testargs
|
||||||
# get results of the openstack_dashboard tests
|
# get results of the openstack_dashboard tests
|
||||||
|
Loading…
Reference in New Issue
Block a user