Merge pull request #1138 from edx/zoldak/locked-asset-tests
Refactor upload tests and add locked asset tests for registered user
This commit is contained in:
@@ -5,17 +5,16 @@ Feature: CMS.Upload Files
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can upload files
|
||||
Given I have opened a new course in Studio
|
||||
And I go to the files and uploads page
|
||||
Given I am at the files and upload page of a Studio course
|
||||
When I upload the file "test"
|
||||
Then I should see the file "test" was uploaded
|
||||
And The url for the file "test" is valid
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can upload multiple files
|
||||
Given I have opened a new course in studio
|
||||
And I go to the files and uploads page
|
||||
When I upload the files "test","test2"
|
||||
Given I am at the files and upload page of a Studio course
|
||||
When I upload the files "test,test2"
|
||||
Then I should see the file "test" was uploaded
|
||||
And I should see the file "test2" was uploaded
|
||||
And The url for the file "test2" is valid
|
||||
@@ -24,8 +23,7 @@ Feature: CMS.Upload Files
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can update files
|
||||
Given I have opened a new course in studio
|
||||
And I go to the files and uploads page
|
||||
Given I am at the files and upload page of a Studio course
|
||||
When I upload the file "test"
|
||||
And I upload the file "test"
|
||||
Then I should see only one "test"
|
||||
@@ -33,8 +31,7 @@ Feature: CMS.Upload Files
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can delete uploaded files
|
||||
Given I have opened a new course in studio
|
||||
And I go to the files and uploads page
|
||||
Given I am at the files and upload page of a Studio course
|
||||
When I upload the file "test"
|
||||
And I delete the file "test"
|
||||
Then I should not see the file "test" was uploaded
|
||||
@@ -43,16 +40,14 @@ Feature: CMS.Upload Files
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can download files
|
||||
Given I have opened a new course in studio
|
||||
And I go to the files and uploads page
|
||||
Given I am at the files and upload page of a Studio course
|
||||
When I upload the file "test"
|
||||
Then I can download the correct "test" file
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can download updated files
|
||||
Given I have opened a new course in studio
|
||||
And I go to the files and uploads page
|
||||
Given I am at the files and upload page of a Studio course
|
||||
When I upload the file "test"
|
||||
And I modify "test"
|
||||
And I reload the page
|
||||
@@ -62,57 +57,59 @@ Feature: CMS.Upload Files
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can lock assets through asset index
|
||||
Given I have opened a new course in studio
|
||||
And I go to the files and uploads page
|
||||
When I upload the file "test"
|
||||
And I lock "test"
|
||||
Then "test" is locked
|
||||
Given I am at the files and upload page of a Studio course
|
||||
When I upload an asset
|
||||
And I lock the asset
|
||||
Then the asset is locked
|
||||
And I see a "saving" notification
|
||||
And I reload the page
|
||||
Then "test" is locked
|
||||
Then the asset is locked
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Users can unlock assets through asset index
|
||||
Given I have opened a course with a locked asset "test"
|
||||
And I unlock "test"
|
||||
Then "test" is unlocked
|
||||
Given I have created a course with a locked asset
|
||||
When I unlock the asset
|
||||
Then the asset is unlocked
|
||||
And I see a "saving" notification
|
||||
And I reload the page
|
||||
Then "test" is unlocked
|
||||
Then the asset is unlocked
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
# TODO: work with Jay
|
||||
# @skip_safari
|
||||
# Scenario: Locked assets can't be viewed if logged in as unregistered user
|
||||
# Given I have opened a course with a locked asset "locked.html"
|
||||
# Then the asset "locked.html" can be clicked from the asset index
|
||||
# And the user "bob" exists
|
||||
# And "bob" logs in
|
||||
# Then the asset "locked.html" is protected
|
||||
@skip_safari
|
||||
Scenario: Locked assets can't be viewed if logged in as an unregistered user
|
||||
Given I have created a course with a locked asset
|
||||
And the user "bob" exists
|
||||
When "bob" logs in
|
||||
Then the asset is protected
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Locked assets can be viewed if logged in as a registered user
|
||||
Given I have created a course with a locked asset
|
||||
And the user "bob" exists
|
||||
And the user "bob" is enrolled in the course
|
||||
When "bob" logs in
|
||||
Then the asset is viewable
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Locked assets can't be viewed if logged out
|
||||
Given I have opened a course with a locked asset "locked.html"
|
||||
# Note that logging out doesn't really matter at the moment-
|
||||
# the asset will be protected because the user sent to middleware is the anonymous user.
|
||||
# Need to work with Jay.
|
||||
And I log out
|
||||
Then the asset "locked.html" is protected
|
||||
Given I have created a course with a locked asset
|
||||
When I log out
|
||||
Then the asset is protected
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Locked assets can be viewed with is_staff account
|
||||
Given I have opened a course with a locked asset "locked.html"
|
||||
Given I have created a course with a locked asset
|
||||
And the user "staff" exists as a course is_staff
|
||||
And "staff" logs in
|
||||
Then the asset "locked.html" can be clicked from the asset index
|
||||
When "staff" logs in
|
||||
Then the asset is viewable
|
||||
|
||||
# Uploading isn't working on safari with sauce labs
|
||||
@skip_safari
|
||||
Scenario: Unlocked assets can be viewed by anyone
|
||||
Given I have opened a course with a unlocked asset "unlocked.html"
|
||||
Then the asset "unlocked.html" can be clicked from the asset index
|
||||
And I log out
|
||||
Then the asset "unlocked.html" is viewable
|
||||
Given I have created a course with a unlocked asset
|
||||
When I log out
|
||||
Then the asset is viewable
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
#pylint: disable=W0621
|
||||
|
||||
from lettuce import world, step
|
||||
from lettuce.django import django_url
|
||||
from django.conf import settings
|
||||
import requests
|
||||
import string
|
||||
import random
|
||||
import os
|
||||
from django.contrib.auth.models import User
|
||||
from student.models import CourseEnrollment
|
||||
from splinter.request_handler.status_code import HttpResponseError
|
||||
from nose.tools import assert_equal, assert_not_equal # pylint: disable=E0611
|
||||
|
||||
|
||||
TEST_ROOT = settings.COMMON_TEST_DATA_ROOT
|
||||
ASSET_NAMES_CSS = 'td.name-col > span.title > a.filename'
|
||||
|
||||
@@ -26,7 +29,10 @@ def go_to_uploads(_step):
|
||||
def upload_file(_step, file_name):
|
||||
upload_css = 'a.upload-button'
|
||||
world.css_click(upload_css)
|
||||
#uploading the file itself
|
||||
|
||||
_write_test_file(file_name, "test file")
|
||||
|
||||
# uploading the file itself
|
||||
path = os.path.join(TEST_ROOT, 'uploads/', file_name)
|
||||
world.browser.execute_script("$('input.file-input').css('display', 'block')")
|
||||
world.browser.attach_file('file', os.path.abspath(path))
|
||||
@@ -34,19 +40,20 @@ def upload_file(_step, file_name):
|
||||
world.css_click(close_css)
|
||||
|
||||
|
||||
@step(u'I upload the files (".*")$')
|
||||
@step(u'I upload the files "([^"]*)"$')
|
||||
def upload_files(_step, files_string):
|
||||
# Turn files_string to a list of file names
|
||||
# files_string should be comma separated with no spaces.
|
||||
files = files_string.split(",")
|
||||
files = map(lambda x: string.strip(x, ' "\''), files)
|
||||
|
||||
upload_css = 'a.upload-button'
|
||||
world.css_click(upload_css)
|
||||
#uploading the files
|
||||
for f in files:
|
||||
path = os.path.join(TEST_ROOT, 'uploads/', f)
|
||||
|
||||
# uploading the files
|
||||
for filename in files:
|
||||
_write_test_file(filename, "test file")
|
||||
path = os.path.join(TEST_ROOT, 'uploads/', filename)
|
||||
world.browser.execute_script("$('input.file-input').css('display', 'block')")
|
||||
world.browser.attach_file('file', os.path.abspath(path))
|
||||
|
||||
close_css = 'a.close-button'
|
||||
world.css_click(close_css)
|
||||
|
||||
@@ -104,13 +111,13 @@ def check_download(_step, file_name):
|
||||
r = get_file(file_name)
|
||||
downloaded_text = r.text
|
||||
assert cur_text == downloaded_text
|
||||
#resetting the file back to its original state
|
||||
# resetting the file back to its original state
|
||||
_write_test_file(file_name, "This is an arbitrary file for testing uploads")
|
||||
|
||||
|
||||
def _write_test_file(file_name, text):
|
||||
path = os.path.join(TEST_ROOT, 'uploads/', file_name)
|
||||
#resetting the file back to its original state
|
||||
# resetting the file back to its original state
|
||||
with open(os.path.abspath(path), 'w') as cur_file:
|
||||
cur_file.write(text)
|
||||
|
||||
@@ -121,68 +128,68 @@ def modify_upload(_step, file_name):
|
||||
_write_test_file(file_name, new_text)
|
||||
|
||||
|
||||
@step(u'I (lock|unlock) "([^"]*)"$')
|
||||
def lock_unlock_file(_step, _lock_state, file_name):
|
||||
index = get_index(file_name)
|
||||
assert index != -1
|
||||
@step(u'I upload an asset$')
|
||||
def upload_an_asset(step):
|
||||
step.given('I upload the file "asset.html"')
|
||||
|
||||
|
||||
@step(u'I (lock|unlock) the asset$')
|
||||
def lock_unlock_file(_step, _lock_state):
|
||||
index = get_index('asset.html')
|
||||
assert index != -1, 'Expected to find an asset but could not.'
|
||||
|
||||
# Warning: this is a misnomer, it really only toggles the
|
||||
# lock state. TODO: fix it.
|
||||
lock_css = "input.lock-checkbox"
|
||||
world.css_find(lock_css)[index].click()
|
||||
|
||||
|
||||
@step(u'Then "([^"]*)" is (locked|unlocked)$')
|
||||
def verify_lock_unlock_file(_step, file_name, lock_state):
|
||||
index = get_index(file_name)
|
||||
assert index != -1
|
||||
@step(u'the user "([^"]*)" is enrolled in the course$')
|
||||
def user_foo_is_enrolled_in_the_course(step, name):
|
||||
world.create_user(name, 'test')
|
||||
user = User.objects.get(username=name)
|
||||
|
||||
course_id = world.scenario_dict['COURSE'].location.course_id
|
||||
CourseEnrollment.enroll(user, course_id)
|
||||
|
||||
|
||||
@step(u'Then the asset is (locked|unlocked)$')
|
||||
def verify_lock_unlock_file(_step, lock_state):
|
||||
index = get_index('asset.html')
|
||||
assert index != -1, 'Expected to find an asset but could not.'
|
||||
lock_css = "input.lock-checkbox"
|
||||
checked = world.css_find(lock_css)[index]._element.get_attribute('checked')
|
||||
assert_equal(lock_state == "locked", bool(checked))
|
||||
|
||||
|
||||
@step(u'I have opened a course with a (locked|unlocked) asset "([^"]*)"$')
|
||||
def open_course_with_locked(step, lock_state, file_name):
|
||||
@step(u'I am at the files and upload page of a Studio course')
|
||||
def at_upload_page(step):
|
||||
step.given('I have opened a new course in studio')
|
||||
step.given('I go to the files and uploads page')
|
||||
_write_test_file(file_name, "test file")
|
||||
step.given('I upload the file "' + file_name + '"')
|
||||
|
||||
|
||||
@step(u'I have created a course with a (locked|unlocked) asset$')
|
||||
def open_course_with_locked(step, lock_state):
|
||||
step.given('I am at the files and upload page of a Studio course')
|
||||
step.given('I upload the file "asset.html"')
|
||||
|
||||
if lock_state == "locked":
|
||||
step.given('I lock "' + file_name + '"')
|
||||
step.given('I lock the asset')
|
||||
step.given('I reload the page')
|
||||
|
||||
|
||||
@step(u'Then the asset "([^"]*)" is (viewable|protected)$')
|
||||
def view_asset(_step, file_name, status):
|
||||
url = '/c4x/MITx/999/asset/' + file_name
|
||||
@step(u'Then the asset is (viewable|protected)$')
|
||||
def view_asset(_step, status):
|
||||
url = django_url('/c4x/MITx/999/asset/asset.html')
|
||||
if status == 'viewable':
|
||||
world.visit(url)
|
||||
_verify_body_text()
|
||||
expected_text = 'test file'
|
||||
else:
|
||||
error_thrown = False
|
||||
try:
|
||||
world.visit(url)
|
||||
except Exception as e:
|
||||
assert e.status_code == 403
|
||||
error_thrown = True
|
||||
assert error_thrown
|
||||
expected_text = 'Unauthorized'
|
||||
|
||||
|
||||
@step(u'Then the asset "([^"]*)" can be clicked from the asset index$')
|
||||
def click_asset_from_index(step, file_name):
|
||||
# This is not ideal, but I'm having trouble with the middleware not having
|
||||
# the same user in the request when I hit the URL directly.
|
||||
course_link_css = 'a.course-link'
|
||||
world.css_click(course_link_css)
|
||||
step.given("I go to the files and uploads page")
|
||||
index = get_index(file_name)
|
||||
assert index != -1
|
||||
world.css_click('a.filename', index=index)
|
||||
_verify_body_text()
|
||||
|
||||
|
||||
def _verify_body_text():
|
||||
def verify_text(driver):
|
||||
return world.css_text('body') == 'test file'
|
||||
|
||||
world.wait_for(verify_text)
|
||||
# Note that world.visit would trigger a 403 error instead of displaying "Unauthorized"
|
||||
# Instead, we can drop back into the selenium driver get command.
|
||||
world.browser.driver.get(url)
|
||||
assert_equal(world.css_text('body'),expected_text)
|
||||
|
||||
|
||||
@step('I see a confirmation that the file was deleted$')
|
||||
|
||||
@@ -2,17 +2,10 @@
|
||||
# pylint: disable=W0621
|
||||
|
||||
from lettuce import world
|
||||
from .factories import *
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth import authenticate, login
|
||||
from django.contrib.auth.middleware import AuthenticationMiddleware
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from student.models import CourseEnrollment
|
||||
from xmodule.modulestore.django import editable_modulestore
|
||||
from xmodule.contentstore.django import contentstore
|
||||
from urllib import quote_plus
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -22,7 +15,7 @@ def create_user(uname, password):
|
||||
if len(User.objects.filter(username=uname)) > 0:
|
||||
return
|
||||
|
||||
portal_user = UserFactory.build(username=uname, email=uname + '@edx.org')
|
||||
portal_user = world.UserFactory.build(username=uname, email=uname + '@edx.org')
|
||||
portal_user.set_password(password)
|
||||
portal_user.save()
|
||||
|
||||
@@ -30,7 +23,7 @@ def create_user(uname, password):
|
||||
registration.register(portal_user)
|
||||
registration.activate()
|
||||
|
||||
user_profile = world.UserProfileFactory(user=portal_user)
|
||||
world.UserProfileFactory(user=portal_user)
|
||||
|
||||
|
||||
@world.absorb
|
||||
|
||||
3
common/test/data/uploads/.gitignore
vendored
Normal file
3
common/test/data/uploads/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
test
|
||||
test2
|
||||
asset.html
|
||||
@@ -1 +0,0 @@
|
||||
This is an arbitrary file for testing uploads
|
||||
Reference in New Issue
Block a user