John Postlethwait 65824cb8c8 Fixes to the user form, UI behaviors, and tests.
The message you got upon successful user update
was misleading as it told you all of the fields
were updated, even if no changes were made to
those fields.

Also there was an issue where in this user edit
form, where if can_edit_user was False in the
local_settings file, you could not change the
default project for a user.

Changed the stubbing behavior for tests as well
to allow the use of a decorator to stub your tests
using Mox instead of having to clutter up the
actual test with repetitive Mox stubs.

Fixes Bug #993572

Change-Id: Iaebd6525bb4509a2ec6b350df432f4f60dd35114
2012-05-09 12:41:20 -07:00

332 lines
12 KiB
Python

# 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
from django.core.urlresolvers import reverse
from keystoneclient import exceptions as keystone_exceptions
from mox import IgnoreArg, IsA
from horizon import api
from horizon import test
USERS_INDEX_URL = reverse('horizon:syspanel:users:index')
USER_CREATE_URL = reverse('horizon:syspanel:users:create')
USER_UPDATE_URL = reverse('horizon:syspanel:users:update', args=[1])
class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_list',)})
def test_index(self):
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
self.mox.ReplayAll()
res = self.client.get(USERS_INDEX_URL)
self.assertTemplateUsed(res, 'syspanel/users/index.html')
self.assertItemsEqual(res.context['table'].data, self.users.list())
@test.create_stubs({api: ('user_create',
'tenant_list',
'add_tenant_user_role'),
api.keystone: ('get_default_role',)})
def test_create(self):
user = self.users.get(id="1")
role = self.roles.first()
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
api.user_create(IgnoreArg(),
user.name,
user.email,
user.password,
self.tenant.id,
True).AndReturn(user)
api.keystone.get_default_role(IgnoreArg()).AndReturn(role)
api.add_tenant_user_role(IgnoreArg(), self.tenant.id, user.id, role.id)
self.mox.ReplayAll()
formData = {'method': 'CreateUserForm',
'name': user.name,
'email': user.email,
'password': user.password,
'tenant_id': self.tenant.id,
'confirm_password': user.password}
res = self.client.post(USER_CREATE_URL, formData)
self.assertNoFormErrors(res)
self.assertMessageCount(success=1)
@test.create_stubs({api: ('tenant_list',)})
def test_create_with_password_mismatch(self):
user = self.users.get(id="1")
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
self.mox.ReplayAll()
formData = {'method': 'CreateUserForm',
'name': user.name,
'email': user.email,
'password': user.password,
'tenant_id': self.tenant.id,
'confirm_password': "doesntmatch"}
res = self.client.post(USER_CREATE_URL, formData)
self.assertFormError(res, "form", None, ['Passwords do not match.'])
@test.create_stubs({api: ('tenant_list',)})
def test_create_validation_for_password_too_short(self):
user = self.users.get(id="1")
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
self.mox.ReplayAll()
# check password min-len verification
formData = {'method': 'CreateUserForm',
'name': user.name,
'email': user.email,
'password': 'four',
'tenant_id': self.tenant.id,
'confirm_password': 'four'}
res = self.client.post(USER_CREATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Password must be between 8 and 18 characters.'])
@test.create_stubs({api: ('tenant_list',)})
def test_create_validation_for_password_too_long(self):
user = self.users.get(id="1")
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
self.mox.ReplayAll()
# check password min-len verification
formData = {'method': 'CreateUserForm',
'name': user.name,
'email': user.email,
'password': 'MoreThanEighteenChars',
'tenant_id': self.tenant.id,
'confirm_password': 'MoreThanEighteenChars'}
res = self.client.post(USER_CREATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Password must be between 8 and 18 characters.'])
@test.create_stubs({api: ('user_get',
'tenant_list',
'user_update_tenant',
'user_update_password'),
api.keystone: ('user_update',)})
def test_update(self):
user = self.users.get(id="1")
api.user_get(IsA(http.HttpRequest), '1',
admin=True).AndReturn(user)
api.tenant_list(IgnoreArg(),
admin=True).AndReturn(self.tenants.list())
api.keystone.user_update(IsA(http.HttpRequest),
user.id,
email=u'test@example.com',
name=u'test_user').AndReturn(None)
api.user_update_tenant(IsA(http.HttpRequest),
user.id,
self.tenant.id).AndReturn(None)
api.user_update_password(IsA(http.HttpRequest),
user.id,
IgnoreArg()).AndReturn(None)
self.mox.ReplayAll()
formData = {'method': 'UpdateUserForm',
'id': user.id,
'name': user.name,
'email': user.email,
'password': 'normalpwd',
'tenant_id': self.tenant.id,
'confirm_password': 'normalpwd'}
res = self.client.post(USER_UPDATE_URL, formData)
self.assertNoFormErrors(res)
@test.create_stubs({api: ('user_get',
'tenant_list',
'user_update_tenant',
'keystone_can_edit_user')})
def test_update_with_keystone_can_edit_user_false(self):
user = self.users.get(id="1")
api.user_get(IsA(http.HttpRequest),
'1',
admin=True).AndReturn(user)
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
api.keystone_can_edit_user().AndReturn(False)
api.keystone_can_edit_user().AndReturn(False)
api.user_update_tenant(IsA(http.HttpRequest),
user.id,
self.tenant.id).AndReturn(None)
self.mox.ReplayAll()
formData = {'method': 'UpdateUserForm',
'tenant_id': self.tenant.id,
'id': user.id}
res = self.client.post(USER_UPDATE_URL, formData)
self.assertNoFormErrors(res)
@test.create_stubs({api: ('user_get', 'tenant_list')})
def test_update_validation_for_password_too_short(self):
user = self.users.get(id="1")
api.user_get(IsA(http.HttpRequest), '1',
admin=True).AndReturn(user)
api.tenant_list(IgnoreArg(),
admin=True).AndReturn(self.tenants.list())
self.mox.ReplayAll()
formData = {'method': 'UpdateUserForm',
'id': user.id,
'name': user.name,
'email': user.email,
'password': 't',
'tenant_id': self.tenant.id,
'confirm_password': 't'}
res = self.client.post(USER_UPDATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Password must be between 8 and 18 characters.'])
@test.create_stubs({api: ('user_get', 'tenant_list')})
def test_update_validation_for_password_too_long(self):
user = self.users.get(id="1")
api.user_get(IsA(http.HttpRequest), '1',
admin=True).AndReturn(user)
api.tenant_list(IgnoreArg(),
admin=True).AndReturn(self.tenants.list())
self.mox.ReplayAll()
formData = {'method': 'UpdateUserForm',
'id': user.id,
'name': user.name,
'email': user.email,
'password': 'ThisIsASuperLongPassword',
'tenant_id': self.tenant.id,
'confirm_password': 'ThisIsASuperLongPassword'}
res = self.client.post(USER_UPDATE_URL, formData)
self.assertFormError(
res, "form", 'password',
['Password must be between 8 and 18 characters.'])
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_user(self):
user = self.users.get(id="2")
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
True).AndReturn(user)
self.mox.ReplayAll()
formData = {'action': 'users__enable__%s' % user.id}
res = self.client.post(USERS_INDEX_URL, formData)
self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_disable_user(self):
user = self.users.get(id="2")
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
False).AndReturn(user)
self.mox.ReplayAll()
formData = {'action': 'users__disable__%s' % user.id}
res = self.client.post(USERS_INDEX_URL, formData)
self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_disable_user_exception(self):
user = self.users.get(id="2")
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api_exception = keystone_exceptions.ClientException('apiException',
message='apiException')
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
True).AndRaise(api_exception)
self.mox.ReplayAll()
formData = {'action': 'users__enable__%s' % user.id}
res = self.client.post(USERS_INDEX_URL, formData)
self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
@test.create_stubs({api.keystone: ('user_list',)})
def test_disabling_current_user(self):
for i in range(0, 2):
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
self.mox.ReplayAll()
formData = {'action': 'users__disable__%s' % self.request.user.id}
res = self.client.post(USERS_INDEX_URL, formData, follow=True)
self.assertEqual(list(res.context['messages'])[0].message,
u'You cannot disable the user you are currently '
u'logged in as.')
@test.create_stubs({api.keystone: ('user_list',)})
def test_delete_user_with_improper_permissions(self):
for i in range(0, 2):
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
self.mox.ReplayAll()
formData = {'action': 'users__delete__%s' % self.request.user.id}
res = self.client.post(USERS_INDEX_URL, formData, follow=True)
self.assertEqual(list(res.context['messages'])[0].message,
u'You do not have permission to delete user: %s'
% self.request.user.username)