Acceptance & Jasmine tests for library permissions editor
This commit is contained in:
committed by
E. Kolpakov
parent
93bb1f58cd
commit
d38e69c69a
@@ -256,6 +256,7 @@ define([
|
||||
"js/spec/views/pages/course_outline_spec",
|
||||
"js/spec/views/pages/course_rerun_spec",
|
||||
"js/spec/views/pages/index_spec",
|
||||
"js/spec/views/pages/library_users_spec",
|
||||
|
||||
"js/spec/views/modals/base_modal_spec",
|
||||
"js/spec/views/modals/edit_xblock_spec",
|
||||
|
||||
78
cms/static/js/spec/views/pages/library_users_spec.js
Normal file
78
cms/static/js/spec/views/pages/library_users_spec.js
Normal file
@@ -0,0 +1,78 @@
|
||||
define([
|
||||
"jquery", "js/common_helpers/ajax_helpers", "js/spec_helpers/view_helpers",
|
||||
"js/factories/manage_users_lib", "js/views/utils/view_utils"
|
||||
],
|
||||
function ($, AjaxHelpers, ViewHelpers, ManageUsersFactory, ViewUtils) {
|
||||
"use strict";
|
||||
describe("Library Instructor Access Page", function () {
|
||||
var mockHTML = readFixtures('mock/mock-manage-users-lib.underscore');
|
||||
|
||||
beforeEach(function () {
|
||||
ViewHelpers.installMockAnalytics();
|
||||
appendSetFixtures(mockHTML);
|
||||
ManageUsersFactory(
|
||||
"Mock Library",
|
||||
["honor@example.com", "audit@example.com", "staff@example.com"],
|
||||
"dummy_change_role_url"
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
ViewHelpers.removeMockAnalytics();
|
||||
});
|
||||
|
||||
it("can give a user permission to use the library", function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var reloadSpy = spyOn(ViewUtils, 'reload');
|
||||
$('.create-user-button').click();
|
||||
expect($('.wrapper-create-user')).toHaveClass('is-shown');
|
||||
$('.user-email-input').val('other@example.com');
|
||||
$('.form-create.create-user .action-primary').click();
|
||||
AjaxHelpers.expectJsonRequest(requests, 'POST', 'dummy_change_role_url', {role: 'library_user'});
|
||||
AjaxHelpers.respondWithJson(requests, {'result': 'ok'});
|
||||
expect(reloadSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("can cancel adding a user to the library", function () {
|
||||
$('.create-user-button').click();
|
||||
$('.form-create.create-user .action-secondary').click();
|
||||
expect($('.wrapper-create-user')).not.toHaveClass('is-shown');
|
||||
});
|
||||
|
||||
it("displays an error when the required field is blank", function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
$('.create-user-button').click();
|
||||
$('.user-email-input').val('');
|
||||
var errorPromptSelector = '.wrapper-prompt.is-shown .prompt.error';
|
||||
expect($(errorPromptSelector).length).toEqual(0);
|
||||
$('.form-create.create-user .action-primary').click();
|
||||
expect($(errorPromptSelector).length).toEqual(1);
|
||||
expect($(errorPromptSelector)).toContainText('You must enter a valid email address');
|
||||
expect(requests.length).toEqual(0);
|
||||
});
|
||||
|
||||
it("displays an error when the user has already been added", function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
$('.create-user-button').click();
|
||||
$('.user-email-input').val('honor@example.com');
|
||||
var warningPromptSelector = '.wrapper-prompt.is-shown .prompt.warning';
|
||||
expect($(warningPromptSelector).length).toEqual(0);
|
||||
$('.form-create.create-user .action-primary').click();
|
||||
expect($(warningPromptSelector).length).toEqual(1);
|
||||
expect($(warningPromptSelector)).toContainText('Already a library team member');
|
||||
expect(requests.length).toEqual(0);
|
||||
});
|
||||
|
||||
|
||||
it("can remove a user's permission to access the library", function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var reloadSpy = spyOn(ViewUtils, 'reload');
|
||||
$('.user-item[data-email="honor@example.com"] .action-delete .delete').click();
|
||||
expect($('.wrapper-prompt.is-shown .prompt.warning').length).toEqual(1);
|
||||
$('.wrapper-prompt.is-shown .action-primary').click();
|
||||
AjaxHelpers.expectJsonRequest(requests, 'DELETE', 'dummy_change_role_url', {role: null});
|
||||
AjaxHelpers.respondWithJson(requests, {'result': 'ok'});
|
||||
expect(reloadSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
146
cms/templates/js/mock/mock-manage-users-lib.underscore
Normal file
146
cms/templates/js/mock/mock-manage-users-lib.underscore
Normal file
@@ -0,0 +1,146 @@
|
||||
<div class="wrapper-mast wrapper">
|
||||
<header class="mast has-actions has-subtitle">
|
||||
<h1 class="page-header">
|
||||
<small class="subtitle">Settings</small>
|
||||
<span class="sr">> </span>Instructor Access
|
||||
</h1>
|
||||
|
||||
<nav class="nav-actions">
|
||||
<h3 class="sr">Page Actions</h3>
|
||||
<ul>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="button new-button create-user-button"><i class="icon-plus"></i> Add Instructor</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="wrapper-content wrapper">
|
||||
<section class="content">
|
||||
<article class="content-primary" role="main">
|
||||
<div class="wrapper-create-element animate wrapper-create-user">
|
||||
<form class="form-create create-user" id="create-user-form" name="create-user-form">
|
||||
<div class="wrapper-form">
|
||||
<h3 class="title">Grant Instructor Access to This Library</h3>
|
||||
|
||||
<fieldset class="form-fields">
|
||||
<legend class="sr">New Instructor Information</legend>
|
||||
|
||||
<ol class="list-input">
|
||||
<li class="field text required create-user-email">
|
||||
<label for="user-email-input">User's Email Address</label>
|
||||
<input id="user-email-input" class="user-email-input" name="user-email" type="text" placeholder="example: username@domain.com" value="">
|
||||
<span class="tip tip-stacked">Please provide the email address of the instructor you'd like to add</span>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button class="action action-primary" type="submit">Add User</button>
|
||||
<button class="action action-secondary action-cancel">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<ol class="user-list">
|
||||
|
||||
<li class="user-item" data-email="honor@example.com">
|
||||
|
||||
<span class="wrapper-ui-badge">
|
||||
<span class="flag flag-role flag-role-staff is-hanging">
|
||||
<span class="label sr">Current Role:</span>
|
||||
<span class="value">
|
||||
Staff
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="item-metadata">
|
||||
<h3 class="user-name">
|
||||
<span class="user-username">honor</span>
|
||||
<span class="user-email">
|
||||
<a class="action action-email" href="mailto:honor@example.com" title="send an email message to honor@example.com">honor@example.com</a>
|
||||
</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<ul class="item-actions user-actions">
|
||||
<li class="action action-role">
|
||||
<a href="#" class="make-instructor admin-role add-admin-role">Add Admin Access</span></a>
|
||||
<a href="#" class="make-user admin-role remove-admin-role">Remove Staff Access</span></a>
|
||||
</li>
|
||||
<li class="action action-delete ">
|
||||
<a href="#" class="delete remove-user action-icon" data-tooltip="Remove this user"><i class="icon-trash"></i><span class="sr">Delete the user, honor</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="user-item" data-email="audit@example.com">
|
||||
|
||||
<span class="wrapper-ui-badge">
|
||||
<span class="flag flag-role flag-role-admin is-hanging">
|
||||
<span class="label sr">Current Role:</span>
|
||||
<span class="value">
|
||||
Admin
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="item-metadata">
|
||||
<h3 class="user-name">
|
||||
<span class="user-username">audit</span>
|
||||
<span class="user-email">
|
||||
<a class="action action-email" href="mailto:audit@example.com" title="send an email message to audit@example.com">audit@example.com</a>
|
||||
</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<ul class="item-actions user-actions">
|
||||
<li class="action action-role">
|
||||
<a href="#" class="make-staff admin-role remove-admin-role">Remove Admin Access</span></a>
|
||||
</li>
|
||||
<li class="action action-delete ">
|
||||
<a href="#" class="delete remove-user action-icon" data-tooltip="Remove this user"><i class="icon-trash"></i><span class="sr">Delete the user, audit</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="user-item" data-email="staff@example.com">
|
||||
|
||||
<span class="wrapper-ui-badge">
|
||||
<span class="flag flag-role flag-role-user is-hanging">
|
||||
<span class="label sr">Current Role:</span>
|
||||
<span class="value">
|
||||
User
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="item-metadata">
|
||||
<h3 class="user-name">
|
||||
<span class="user-username">staff</span>
|
||||
<span class="user-email">
|
||||
<a class="action action-email" href="mailto:staff@example.com" title="send an email message to staff@example.com">staff@example.com</a>
|
||||
</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<ul class="item-actions user-actions">
|
||||
<li class="action action-role">
|
||||
<a href="#" class="make-staff admin-role add-admin-role">Add Staff Access</span></a>
|
||||
</li>
|
||||
<li class="action action-delete ">
|
||||
<a href="#" class="delete remove-user action-icon" data-tooltip="Remove this user"><i class="icon-trash"></i><span class="sr">Delete the user, staff</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
</article>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1746,6 +1746,7 @@ def auto_auth(request):
|
||||
* `staff`: Set to "true" to make the user global staff.
|
||||
* `course_id`: Enroll the student in the course with `course_id`
|
||||
* `roles`: Comma-separated list of roles to grant the student in the course with `course_id`
|
||||
* `no_login`: Define this to create the user but not login
|
||||
|
||||
If username, email, or password are not provided, use
|
||||
randomly generated credentials.
|
||||
@@ -1765,6 +1766,7 @@ def auto_auth(request):
|
||||
if course_id:
|
||||
course_key = CourseLocator.from_string(course_id)
|
||||
role_names = [v.strip() for v in request.GET.get('roles', '').split(',') if v.strip()]
|
||||
login_when_done = 'no_login' not in request.GET
|
||||
|
||||
# Get or create the user object
|
||||
post_data = {
|
||||
@@ -1808,14 +1810,16 @@ def auto_auth(request):
|
||||
user.roles.add(role)
|
||||
|
||||
# Log in as the user
|
||||
user = authenticate(username=username, password=password)
|
||||
login(request, user)
|
||||
if login_when_done:
|
||||
user = authenticate(username=username, password=password)
|
||||
login(request, user)
|
||||
|
||||
create_comments_service_user(user)
|
||||
|
||||
# Provide the user with a valid CSRF token
|
||||
# then return a 200 response
|
||||
success_msg = u"Logged in user {0} ({1}) with password {2} and user_id {3}".format(
|
||||
success_msg = u"{} user {} ({}) with password {} and user_id {}".format(
|
||||
u"Logged in" if login_when_done else "Created",
|
||||
username, email, password, user.id
|
||||
)
|
||||
response = HttpResponse(success_msg)
|
||||
|
||||
@@ -15,7 +15,7 @@ class AutoAuthPage(PageObject):
|
||||
this url will create a user and log them in.
|
||||
"""
|
||||
|
||||
def __init__(self, browser, username=None, email=None, password=None, staff=None, course_id=None, roles=None):
|
||||
def __init__(self, browser, username=None, email=None, password=None, staff=None, course_id=None, roles=None, no_login=None):
|
||||
"""
|
||||
Auto-auth is an end-point for HTTP GET requests.
|
||||
By default, it will create accounts with random user credentials,
|
||||
@@ -51,6 +51,9 @@ class AutoAuthPage(PageObject):
|
||||
if roles is not None:
|
||||
self._params['roles'] = roles
|
||||
|
||||
if no_login:
|
||||
self._params['no_login'] = True
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
"""
|
||||
@@ -66,7 +69,7 @@ class AutoAuthPage(PageObject):
|
||||
|
||||
def is_browser_on_page(self):
|
||||
message = self.q(css='BODY').text[0]
|
||||
match = re.search(r'Logged in user ([^$]+) with password ([^$]+) and user_id ([^$]+)$', message)
|
||||
match = re.search(r'(Logged in|Created) user ([^$]+) with password ([^$]+) and user_id ([^$]+)$', message)
|
||||
return True if match else False
|
||||
|
||||
def get_user_id(self):
|
||||
|
||||
189
common/test/acceptance/pages/studio/users.py
Normal file
189
common/test/acceptance/pages/studio/users.py
Normal file
@@ -0,0 +1,189 @@
|
||||
"""
|
||||
Page classes to test either the Course Team page or the Library Team page.
|
||||
"""
|
||||
from bok_choy.promise import EmptyPromise
|
||||
from bok_choy.page_object import PageObject
|
||||
from ...tests.helpers import disable_animations
|
||||
from . import BASE_URL
|
||||
|
||||
|
||||
def wait_for_ajax_or_reload(browser):
|
||||
"""
|
||||
Wait for all ajax requests to finish, OR for the page to reload.
|
||||
Normal wait_for_ajax() chokes on occasion if the pages reloads,
|
||||
giving "WebDriverException: Message: u'jQuery is not defined'"
|
||||
"""
|
||||
def _is_ajax_finished():
|
||||
""" Wait for jQuery to finish all AJAX calls, if it is present. """
|
||||
return browser.execute_script("return typeof(jQuery) == 'undefined' || jQuery.active == 0")
|
||||
|
||||
EmptyPromise(_is_ajax_finished, "Finished waiting for ajax requests.").fulfill()
|
||||
|
||||
|
||||
class UsersPage(PageObject):
|
||||
"""
|
||||
Base class for either the Course Team page or the Library Team page
|
||||
"""
|
||||
|
||||
def __init__(self, browser, locator):
|
||||
super(UsersPage, self).__init__(browser)
|
||||
self.locator = locator
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
"""
|
||||
URL to this page - override in subclass
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def is_browser_on_page(self):
|
||||
"""
|
||||
Returns True iff the browser has loaded the page.
|
||||
"""
|
||||
return self.q(css='body.view-team').present
|
||||
|
||||
@property
|
||||
def users(self):
|
||||
"""
|
||||
Return a list of users listed on this page.
|
||||
"""
|
||||
return self.q(css='.user-list .user-item').map(lambda el: UserWrapper(self.browser, el.get_attribute('data-email'))).results
|
||||
|
||||
@property
|
||||
def has_add_button(self):
|
||||
"""
|
||||
Is the "New Team Member" button present?
|
||||
"""
|
||||
return self.q(css='.create-user-button').present
|
||||
|
||||
def click_add_button(self):
|
||||
"""
|
||||
Click on the "New Team Member" button
|
||||
"""
|
||||
self.q(css='.create-user-button').click()
|
||||
|
||||
@property
|
||||
def new_user_form_visible(self):
|
||||
""" Is the new user form visible? """
|
||||
return self.q(css='.form-create.create-user .user-email-input').visible
|
||||
|
||||
def set_new_user_email(self, email):
|
||||
""" Set the value of the "New User Email Address" field. """
|
||||
self.q(css='.form-create.create-user .user-email-input').fill(email)
|
||||
|
||||
def click_submit_new_user_form(self):
|
||||
""" Submit the "New User" form """
|
||||
self.q(css='.form-create.create-user .action-primary').click()
|
||||
wait_for_ajax_or_reload(self.browser)
|
||||
|
||||
|
||||
class LibraryUsersPage(UsersPage):
|
||||
"""
|
||||
Library Team page in Studio
|
||||
"""
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
"""
|
||||
URL to the "User Access" page for the given library.
|
||||
"""
|
||||
return "{}/library/{}/team/".format(BASE_URL, unicode(self.locator))
|
||||
|
||||
|
||||
class UserWrapper(PageObject):
|
||||
"""
|
||||
A PageObject representing a wrapper around a user listed on the course/library team page.
|
||||
"""
|
||||
url = None
|
||||
COMPONENT_BUTTONS = {
|
||||
'basic_tab': '.editor-tabs li.inner_tab_wrap:nth-child(1) > a',
|
||||
'advanced_tab': '.editor-tabs li.inner_tab_wrap:nth-child(2) > a',
|
||||
'save_settings': '.action-save',
|
||||
}
|
||||
|
||||
def __init__(self, browser, email):
|
||||
super(UserWrapper, self).__init__(browser)
|
||||
self.email = email
|
||||
self.selector = '.user-list .user-item[data-email="{}"]'.format(self.email)
|
||||
|
||||
def is_browser_on_page(self):
|
||||
"""
|
||||
Sanity check that our wrapper element is on the page.
|
||||
"""
|
||||
return self.q(css=self.selector).present
|
||||
|
||||
def _bounded_selector(self, selector):
|
||||
"""
|
||||
Return `selector`, but limited to this particular user entry's context
|
||||
"""
|
||||
return '{} {}'.format(self.selector, selector)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Get this user's username, as displayed. """
|
||||
return self.q(css=self._bounded_selector('.user-username')).text[0]
|
||||
|
||||
@property
|
||||
def role_label(self):
|
||||
""" Get this user's role, as displayed. """
|
||||
return self.q(css=self._bounded_selector('.flag-role .value')).text[0]
|
||||
|
||||
@property
|
||||
def is_current_user(self):
|
||||
""" Does the UI indicate that this is the current user? """
|
||||
return self.q(css=self._bounded_selector('.flag-role .msg-you')).present
|
||||
|
||||
@property
|
||||
def can_promote(self):
|
||||
""" Can this user be promoted to a more powerful role? """
|
||||
return self.q(css=self._bounded_selector('.add-admin-role')).present
|
||||
|
||||
@property
|
||||
def promote_button_text(self):
|
||||
""" What does the promote user button say? """
|
||||
return self.q(css=self._bounded_selector('.add-admin-role')).text[0]
|
||||
|
||||
def click_promote(self):
|
||||
""" Click on the button to promote this user to the more powerful role """
|
||||
self.q(css=self._bounded_selector('.add-admin-role')).click()
|
||||
wait_for_ajax_or_reload(self.browser)
|
||||
|
||||
@property
|
||||
def can_demote(self):
|
||||
""" Can this user be demoted to a less powerful role? """
|
||||
return self.q(css=self._bounded_selector('.remove-admin-role')).present
|
||||
|
||||
@property
|
||||
def demote_button_text(self):
|
||||
""" What does the demote user button say? """
|
||||
return self.q(css=self._bounded_selector('.remove-admin-role')).text[0]
|
||||
|
||||
def click_demote(self):
|
||||
""" Click on the button to demote this user to the less powerful role """
|
||||
self.q(css=self._bounded_selector('.remove-admin-role')).click()
|
||||
wait_for_ajax_or_reload(self.browser)
|
||||
|
||||
@property
|
||||
def can_delete(self):
|
||||
""" Can this user be deleted? """
|
||||
return self.q(css=self._bounded_selector('.action-delete:not(.is-disabled) .remove-user')).present
|
||||
|
||||
def click_delete(self):
|
||||
""" Click the button to delete this user. """
|
||||
disable_animations(self)
|
||||
self.q(css=self._bounded_selector('.remove-user')).click()
|
||||
# We can't use confirm_prompt because its wait_for_ajax is flaky when the page is expected to reload.
|
||||
self.wait_for_element_visibility('.prompt', 'Prompt is visible')
|
||||
self.wait_for_element_visibility('.prompt .action-primary', 'Confirmation button is visible')
|
||||
self.q(css='.prompt .action-primary').click()
|
||||
wait_for_ajax_or_reload(self.browser)
|
||||
|
||||
@property
|
||||
def has_no_change_warning(self):
|
||||
""" Does this have a warning in place of the promote/demote buttons? """
|
||||
return self.q(css=self._bounded_selector('.notoggleforyou')).present
|
||||
|
||||
@property
|
||||
def no_change_warning_text(self):
|
||||
""" Text of the warning seen in place of the promote/demote buttons. """
|
||||
return self.q(css=self._bounded_selector('.notoggleforyou')).text[0]
|
||||
@@ -5,8 +5,10 @@ from ddt import ddt, data
|
||||
|
||||
from .base_studio_test import StudioLibraryTest
|
||||
from ...fixtures.course import XBlockFixtureDesc
|
||||
from ...pages.studio.auto_auth import AutoAuthPage
|
||||
from ...pages.studio.utils import add_component
|
||||
from ...pages.studio.library import LibraryPage
|
||||
from ...pages.studio.users import LibraryUsersPage
|
||||
|
||||
|
||||
@ddt
|
||||
@@ -306,3 +308,138 @@ class LibraryNavigationTest(StudioLibraryTest):
|
||||
self.assertEqual(self.lib_page.xblocks[0].name, '1')
|
||||
self.assertEqual(self.lib_page.xblocks[-1].name, '11')
|
||||
self.assertEqual(self.lib_page.get_page_number(), '1')
|
||||
|
||||
|
||||
class LibraryUsersPageTest(StudioLibraryTest):
|
||||
"""
|
||||
Test the functionality of the library "Instructor Access" page.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(LibraryUsersPageTest, self).setUp()
|
||||
|
||||
# Create a second user for use in these tests:
|
||||
AutoAuthPage(self.browser, username="second", email="second@example.com", no_login=True).visit()
|
||||
|
||||
self.page = LibraryUsersPage(self.browser, self.library_key)
|
||||
self.page.visit()
|
||||
|
||||
def _expect_refresh(self):
|
||||
"""
|
||||
Wait for the page to reload.
|
||||
"""
|
||||
self.page = LibraryUsersPage(self.browser, self.library_key).wait_for_page()
|
||||
|
||||
def test_user_management(self):
|
||||
"""
|
||||
Scenario: Ensure that we can edit the permissions of users.
|
||||
Given I have a library in Studio where I am the only admin
|
||||
assigned (which is the default for a newly-created library)
|
||||
And I navigate to Library "Instructor Access" Page in Studio
|
||||
Then there should be one user listed (myself), and I must
|
||||
not be able to remove myself or my instructor privilege.
|
||||
|
||||
When I click Add Intructor
|
||||
Then I see a form to complete
|
||||
When I complete the form and submit it
|
||||
Then I can see the new user is listed as a "User" of the library
|
||||
|
||||
When I click to Add Staff permissions to the new user
|
||||
Then I can see the new user has staff permissions and that I am now
|
||||
able to promote them to an Admin or remove their staff permissions.
|
||||
|
||||
When I click to Add Admin permissions to the new user
|
||||
Then I can see the new user has admin permissions and that I can now
|
||||
remove Admin permissions from either user.
|
||||
"""
|
||||
def check_is_only_admin(user):
|
||||
"""
|
||||
Ensure user is an admin user and cannot be removed.
|
||||
(There must always be at least one admin user.)
|
||||
"""
|
||||
self.assertIn("admin", user.role_label.lower())
|
||||
self.assertFalse(user.can_promote)
|
||||
self.assertFalse(user.can_demote)
|
||||
self.assertFalse(user.can_delete)
|
||||
self.assertTrue(user.has_no_change_warning)
|
||||
self.assertIn("Promote another member to Admin to remove admin rights", user.no_change_warning_text)
|
||||
|
||||
self.assertEqual(len(self.page.users), 1)
|
||||
user = self.page.users[0]
|
||||
self.assertTrue(user.is_current_user)
|
||||
check_is_only_admin(user)
|
||||
|
||||
# Add a new user:
|
||||
|
||||
self.assertTrue(self.page.has_add_button)
|
||||
self.assertFalse(self.page.new_user_form_visible)
|
||||
self.page.click_add_button()
|
||||
self.assertTrue(self.page.new_user_form_visible)
|
||||
self.page.set_new_user_email('second@example.com')
|
||||
self.page.click_submit_new_user_form()
|
||||
|
||||
# Check the new user's listing:
|
||||
|
||||
def get_two_users():
|
||||
"""
|
||||
Expect two users to be listed, one being me, and another user.
|
||||
Returns me, them
|
||||
"""
|
||||
users = self.page.users
|
||||
self.assertEqual(len(users), 2)
|
||||
self.assertEqual(len([u for u in users if u.is_current_user]), 1)
|
||||
if users[0].is_current_user:
|
||||
return users[0], users[1]
|
||||
else:
|
||||
return users[1], users[0]
|
||||
|
||||
self._expect_refresh()
|
||||
user_me, them = get_two_users()
|
||||
check_is_only_admin(user_me)
|
||||
|
||||
self.assertIn("user", them.role_label.lower())
|
||||
self.assertTrue(them.can_promote)
|
||||
self.assertIn("Add Staff Access", them.promote_button_text)
|
||||
self.assertFalse(them.can_demote)
|
||||
self.assertTrue(them.can_delete)
|
||||
self.assertFalse(them.has_no_change_warning)
|
||||
|
||||
# Add Staff permissions to the new user:
|
||||
|
||||
them.click_promote()
|
||||
self._expect_refresh()
|
||||
user_me, them = get_two_users()
|
||||
check_is_only_admin(user_me)
|
||||
|
||||
self.assertIn("staff", them.role_label.lower())
|
||||
self.assertTrue(them.can_promote)
|
||||
self.assertIn("Add Admin Access", them.promote_button_text)
|
||||
self.assertTrue(them.can_demote)
|
||||
self.assertIn("Remove Staff Access", them.demote_button_text)
|
||||
self.assertTrue(them.can_delete)
|
||||
self.assertFalse(them.has_no_change_warning)
|
||||
|
||||
# Add Admin permissions to the new user:
|
||||
|
||||
them.click_promote()
|
||||
self._expect_refresh()
|
||||
user_me, them = get_two_users()
|
||||
self.assertIn("admin", user_me.role_label.lower())
|
||||
self.assertFalse(user_me.can_promote)
|
||||
self.assertTrue(user_me.can_demote)
|
||||
self.assertTrue(user_me.can_delete)
|
||||
self.assertFalse(user_me.has_no_change_warning)
|
||||
|
||||
self.assertIn("admin", them.role_label.lower())
|
||||
self.assertFalse(them.can_promote)
|
||||
self.assertTrue(them.can_demote)
|
||||
self.assertIn("Remove Admin Access", them.demote_button_text)
|
||||
self.assertTrue(them.can_delete)
|
||||
self.assertFalse(them.has_no_change_warning)
|
||||
|
||||
# Delete the new user:
|
||||
|
||||
them.click_delete()
|
||||
self._expect_refresh()
|
||||
self.assertEqual(len(self.page.users), 1)
|
||||
user = self.page.users[0]
|
||||
self.assertTrue(user.is_current_user)
|
||||
|
||||
Reference in New Issue
Block a user