Commit 7df62ee8 by Calen Pennington Committed by GitHub

Merge pull request #14350 from edx/release-candidate

Merge release-candidate to release
parents f154f8c1 7f66d011
...@@ -981,6 +981,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F ...@@ -981,6 +981,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
"release_date": release_date, "release_date": release_date,
"visibility_state": visibility_state, "visibility_state": visibility_state,
"has_explicit_staff_lock": xblock.fields['visible_to_staff_only'].is_set_on(xblock), "has_explicit_staff_lock": xblock.fields['visible_to_staff_only'].is_set_on(xblock),
"self_paced": is_self_paced(course),
"start": xblock.fields['start'].to_json(xblock.start), "start": xblock.fields['start'].to_json(xblock.start),
"graded": xblock.graded, "graded": xblock.graded,
"due_date": get_default_time_display(xblock.due), "due_date": get_default_time_display(xblock.due),
......
...@@ -712,7 +712,10 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview', ...@@ -712,7 +712,10 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
return $.extend( return $.extend(
{}, {},
AbstractVisibilityEditor.prototype.getContext.call(this), AbstractVisibilityEditor.prototype.getContext.call(this),
{hide_after_due: this.modelVisibility() === 'hide_after_due'} {
hide_after_due: this.modelVisibility() === 'hide_after_due',
self_paced: this.model.get('self_paced') === true
}
); );
} }
}); });
......
...@@ -12,9 +12,19 @@ ...@@ -12,9 +12,19 @@
<li class="field-radio"> <li class="field-radio">
<label class="label"> <label class="label">
<input class="input input-radio" name="content-visibility" type="radio" value="hide_after_due" aria-described-by="hide_after_due_description"> <input class="input input-radio" name="content-visibility" type="radio" value="hide_after_due" aria-described-by="hide_after_due_description">
<%- gettext('Hide content after due date') %> <% if (self_paced) { %>
<%- gettext('Hide content after course end date') %>
<% } else { %>
<%- gettext('Hide content after due date') %>
<% } %>
</label> </label>
<p class='field-message' id='hide_after_due_description'> <%- gettext('After the subsection\'s due date has passed, learners can no longer access its content. The subsection remains included in grade calculations.') %> </p> <p class='field-message' id='hide_after_due_description'>
<% if (self_paced) { %>
<%- gettext('After the course\'s end date has passed, learners can no longer access subsection content. The subsection remains included in grade calculations.') %>
<% } else { %>
<%- gettext('After the subsection\'s due date has passed, learners can no longer access its content. The subsection remains included in grade calculations.') %>
<% } %>
</p>
</li> </li>
<li class="field-radio"> <li class="field-radio">
<label class="label"> <label class="label">
...@@ -29,7 +39,7 @@ ...@@ -29,7 +39,7 @@
<% if (hasExplicitStaffLock && !ancestorLocked) { %> <% if (hasExplicitStaffLock && !ancestorLocked) { %>
<p class="tip tip-warning"> <p class="tip tip-warning">
<%- interpolate( <%- interpolate(
gettext('If you select an option other than "%(hide_label)s", after the subsection release date has passed, published units in this subsection will become available to learners unless units are explicitly hidden.'), gettext('If you select an option other than "%(hide_label)s", published units in this subsection become available to learners unless they are explicitly hidden.'),
{ hide_label: hide_label }, { hide_label: hide_label },
true true
) %> ) %>
......
...@@ -201,7 +201,12 @@ if (is_proctored_exam) { ...@@ -201,7 +201,12 @@ if (is_proctored_exam) {
<p> <p>
<% if (xblockInfo.get('hide_after_due')) { %> <% if (xblockInfo.get('hide_after_due')) { %>
<span class="icon fa fa-eye-slash" aria-hidden="true"></span> <span class="icon fa fa-eye-slash" aria-hidden="true"></span>
<span class="status-hide-after-due-value"> <%- gettext("Subsection is hidden after due date") %> </span> <span class="status-hide-after-due-value">
<% if (course.get('self_paced')) { %>
<%- gettext("Subsection is hidden after course end date") %> </span>
<% } else { %>
<%- gettext("Subsection is hidden after due date") %> </span>
<% } %>
<% } %> <% } %>
</p> </p>
</div> </div>
......
...@@ -236,56 +236,26 @@ describe 'Problem', -> ...@@ -236,56 +236,26 @@ describe 'Problem', ->
expect(@problem.el).toHaveHtml contents expect(@problem.el).toHaveHtml contents
expect(window.SR.readTexts).toHaveBeenCalledWith ['no, try again'] expect(window.SR.readTexts).toHaveBeenCalledWith ['no, try again']
it 'tests if all the capa buttons are disabled while submitting', (done)-> it 'tests if the submit button is disabled while submitting and the text changes on the button', ->
deferred = $.Deferred()
self = this self = this
curr_html = @problem.el.html()
runs = -> spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) ->
spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) -> # At this point enableButtons should have been called, making the submit button disabled with text 'submitting'
promise = undefined expect(self.problem.submitButton).toHaveAttr('disabled');
callback expect(self.problem.submitButtonLabel.text()).toBe('Submitting');
success: 'incorrect' callback
contents: 'Incorrect' success: 'incorrect' # does not matter if correct or incorrect here
promise = contents: curr_html
always: (callable) -> promise =
callable() always: (callable) -> callable()
done: (callable) -> done: (callable) -> callable()
callable() # Make sure the submit button is enabled before submitting
spyOn @problem, 'enableAllButtons' $('#input_example_1').val('test').trigger('input')
@problem.submit() expect(@problem.submitButton).not.toHaveAttr('disabled')
expect(@problem.enableAllButtons).toHaveBeenCalledWith false, true @problem.submit()
if jQuery.active == 0 # After submit, the button should not be disabled and should have text as 'Submit'
deferred.resolve() expect(@problem.submitButtonLabel.text()).toBe('Submit')
deferred.promise() expect(@problem.submitButton).not.toHaveAttr('disabled')
runs.call(self).then(->
expect(self.problem.enableAllButtons).toHaveBeenCalledWith true, true
return
).always done
it 'tests the expected change in text of submit button', (done) ->
deferred = $.Deferred()
self = this
runs = ->
spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) ->
promise = undefined
promise =
always: (callable) ->
callable()
done: (callable) ->
callable()
spyOn @problem.submitButtonLabel, 'text'
@problem.submit()
expect(@problem.submitButtonLabel.text).toHaveBeenCalledWith 'Submitting'
if jQuery.active == 0
deferred.resolve()
deferred.promise()
runs.call(self).then(->
expect(self.problem.submitButtonLabel.text).toHaveBeenCalledWith 'Submit'
return
).always done
describe 'submit button on problems', -> describe 'submit button on problems', ->
beforeEach -> beforeEach ->
...@@ -424,27 +394,22 @@ describe 'Problem', -> ...@@ -424,27 +394,22 @@ describe 'Problem', ->
@problem.reset() @problem.reset()
expect($('.notification-gentle-alert .notification-message').text()).toEqual("Error on reset.") expect($('.notification-gentle-alert .notification-message').text()).toEqual("Error on reset.")
it 'tests if all the buttons are disabled and the text of submit button remains same while resetting', (done) -> it 'tests that reset does not enable submit or modify the text while resetting', ->
deferred = $.Deferred()
self = this self = this
curr_html = @problem.el.html()
runs = -> spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) ->
spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) -> # enableButtons should have been called at this point to set them to all disabled
promise = undefined expect(self.problem.submitButton).toHaveAttr('disabled')
promise = always: (callable) -> expect(self.problem.submitButtonLabel.text()).toBe('Submit')
callable() callback(success: 'correct', html: curr_html)
spyOn @problem, 'enableAllButtons' promise =
@problem.reset() always: (callable) -> callable()
expect(@problem.enableAllButtons).toHaveBeenCalledWith false, false # Submit should be disabled
expect(@problem.submitButtonLabel).toHaveText 'Submit' expect(@problem.submitButton).toHaveAttr('disabled')
if jQuery.active == 0 @problem.reset()
deferred.resolve() # Submit should remain disabled
deferred.promise() expect(self.problem.submitButton).toHaveAttr('disabled')
expect(self.problem.submitButtonLabel.text()).toBe('Submit')
runs.call(self).then(->
expect(self.problem.enableAllButtons).toHaveBeenCalledWith true, false
expect(self.problem.submitButtonLabel).toHaveText 'Submit'
).always done
describe 'show', -> describe 'show', ->
beforeEach -> beforeEach ->
...@@ -483,22 +448,14 @@ describe 'Problem', -> ...@@ -483,22 +448,14 @@ describe 'Problem', ->
@problem.show() @problem.show()
expect(@problem.el.find('.show').attr('disabled')).toEqual('disabled') expect(@problem.el.find('.show').attr('disabled')).toEqual('disabled')
it 'sends a SR message when answer is present', (done) -> it 'sends a SR message when answer is present', ->
deferred = $.Deferred()
runs = -> spyOn($, 'postWithPrefix').and.callFake (url, callback) ->
spyOn($, 'postWithPrefix').and.callFake (url, callback) -> callback answers:
callback answers: '1_1': 'answers'
'1_1': 'answers' @problem.show()
@problem.show()
if jQuery.active == 0
deferred.resolve()
deferred.promise()
runs.call(this).then(-> expect(window.SR.readText).toHaveBeenCalledWith 'Answers to this problem are now shown. Navigate through the problem to review it with answers inline.'
expect(window.SR.readText).toHaveBeenCalledWith 'Answers to this problem are now shown. Navigate through the problem to review it with answers inline.'
return
).always done
describe 'multiple choice question', -> describe 'multiple choice question', ->
beforeEach -> beforeEach ->
...@@ -723,28 +680,42 @@ describe 'Problem', -> ...@@ -723,28 +680,42 @@ describe 'Problem', ->
expect($.postWithPrefix).toHaveBeenCalledWith '/problem/Problem1/problem_save', expect($.postWithPrefix).toHaveBeenCalledWith '/problem/Problem1/problem_save',
'foo=1&bar=2', jasmine.any(Function) 'foo=1&bar=2', jasmine.any(Function)
it 'tests if all the buttons are disabled and the text of submit button does not change while saving.', (done) -> it 'tests that save does not enable the submit button or change the text when submit is originally disabled', ->
deferred = $.Deferred()
self = this self = this
curr_html = @problem.el.html() curr_html = @problem.el.html()
runs = -> spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) ->
spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) -> # enableButtons should have been called at this point and the submit button should be unaffected
promise = undefined expect(self.problem.submitButton).toHaveAttr('disabled')
callback(success: 'correct', html: curr_html) expect(self.problem.submitButtonLabel.text()).toBe('Submit')
promise = always: (callable) -> callback(success: 'correct', html: curr_html)
callable() promise =
spyOn @problem, 'enableAllButtons' always: (callable) -> callable()
@problem.save() # Expect submit to be disabled and labeled properly at the start
expect(@problem.enableAllButtons).toHaveBeenCalledWith false, false expect(@problem.submitButton).toHaveAttr('disabled')
expect(@problem.submitButtonLabel).toHaveText 'Submit' expect(@problem.submitButtonLabel.text()).toBe('Submit')
if jQuery.active == 0 @problem.save()
deferred.resolve() # Submit button should have the same state after save has completed
deferred.promise() expect(@problem.submitButton).toHaveAttr('disabled')
expect(@problem.submitButtonLabel.text()).toBe('Submit')
runs.call(self).then(->
expect(self.problem.enableAllButtons).toHaveBeenCalledWith true, false it 'tests that save does not disable the submit button or change the text when submit is originally enabled', ->
expect(self.problem.submitButtonLabel).toHaveText 'Submit' self = this
).always done curr_html = @problem.el.html()
spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) ->
# enableButtons should have been called at this point, and the submit button should be disabled while submitting
expect(self.problem.submitButton).toHaveAttr('disabled')
expect(self.problem.submitButtonLabel.text()).toBe('Submit')
callback(success: 'correct', html: curr_html)
promise =
always: (callable) -> callable()
# Expect submit to be enabled and labeled properly at the start after adding an input
$('#input_example_1').val('test').trigger('input')
expect(@problem.submitButton).not.toHaveAttr('disabled')
expect(@problem.submitButtonLabel.text()).toBe('Submit')
@problem.save()
# Submit button should have the same state after save has completed
expect(@problem.submitButton).not.toHaveAttr('disabled')
expect(@problem.submitButtonLabel.text()).toBe('Submit')
describe 'refreshMath', -> describe 'refreshMath', ->
beforeEach -> beforeEach ->
......
...@@ -36,9 +36,6 @@ ...@@ -36,9 +36,6 @@
} }
return Problem.prototype.enableSubmitButton.apply(that, arguments); return Problem.prototype.enableSubmitButton.apply(that, arguments);
}; };
this.enableAllButtons = function(enable, isFromCheckOperation) { // eslint-disable-line no-unused-vars
return Problem.prototype.enableAllButtons.apply(that, arguments);
};
this.disableAllButtonsWhileRunning = function( this.disableAllButtonsWhileRunning = function(
operationCallback, isFromCheckOperation // eslint-disable-line no-unused-vars operationCallback, isFromCheckOperation // eslint-disable-line no-unused-vars
) { ) {
...@@ -1157,32 +1154,38 @@ ...@@ -1157,32 +1154,38 @@
*/ */
Problem.prototype.disableAllButtonsWhileRunning = function(operationCallback, isFromCheckOperation) { Problem.prototype.disableAllButtonsWhileRunning = function(operationCallback, isFromCheckOperation) {
var that = this; var that = this;
this.enableAllButtons(false, isFromCheckOperation); var allButtons = [this.resetButton, this.saveButton, this.showButton, this.hintButton, this.submitButton];
var initiallyEnabledButtons = allButtons.filter(function(button) {
return !button.attr('disabled');
});
this.enableButtons(initiallyEnabledButtons, false, isFromCheckOperation);
return operationCallback().always(function() { return operationCallback().always(function() {
return that.enableAllButtons(true, isFromCheckOperation); return that.enableButtons(initiallyEnabledButtons, true, isFromCheckOperation);
}); });
}; };
/** /**
* Used to enable/disable all buttons in problem. * Enables/disables buttons by removing/adding the disabled attribute. The submit button is checked
* separately due to the changing text it contains.
* *
* params: * params:
* 'enable' is a boolean to determine enabling/disabling of buttons. * 'buttons' is an array of buttons that will have their 'disabled' attribute modified
* 'isFromCheckOperation' is a boolean to keep track if operation was initiated * 'enable' a boolean to either enable or disable the buttons passed in the first parameter
* 'changeSubmitButtonText' is a boolean to keep track if operation was initiated
* from submit so that text of submit button will also be changed while disabling/enabling * from submit so that text of submit button will also be changed while disabling/enabling
* the submit button. * the submit button.
*/ */
Problem.prototype.enableAllButtons = function(enable, isFromCheckOperation) { Problem.prototype.enableButtons = function(buttons, enable, changeSubmitButtonText) {
// Called by disableAllButtonsWhileRunning to automatically disable all buttons while check,reset, or var that = this;
// save internal are running. Then enable all the buttons again after it is done. buttons.forEach(function(button) {
if (enable) { if (button.hasClass('submit')) {
this.resetButton.add(this.saveButton).add(this.hintButton).add(this.showButton). that.enableSubmitButton(enable, changeSubmitButtonText);
removeAttr('disabled'); } else if (enable) {
} else { button.removeAttr('disabled');
this.resetButton.add(this.saveButton).add(this.hintButton).add(this.showButton). } else {
attr({disabled: 'disabled'}); button.attr({disabled: 'disabled'});
} }
return this.enableSubmitButton(enable, isFromCheckOperation); });
}; };
/** /**
......
...@@ -202,16 +202,16 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -202,16 +202,16 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
raise NotFoundError('Unexpected dispatch type') raise NotFoundError('Unexpected dispatch type')
@classmethod @classmethod
def verify_current_content_visibility(cls, due, hide_after_due): def verify_current_content_visibility(cls, date, hide_after_date):
""" """
Returns whether the content visibility policy passes Returns whether the content visibility policy passes
for the given due date and hide_after_due values and for the given date and hide_after_date values and
the current date-time. the current date-time.
""" """
return ( return (
not due or not date or
not hide_after_due or not hide_after_date or
datetime.now(UTC()) < due datetime.now(UTC()) < date
) )
def student_view(self, context): def student_view(self, context):
...@@ -246,20 +246,17 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -246,20 +246,17 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
runtime user. If so, returns a banner_text or the fragment to runtime user. If so, returns a banner_text or the fragment to
display depending on whether staff is masquerading. display depending on whether staff is masquerading.
""" """
if not self._can_user_view_content(): course = self._get_course()
subsection_format = (self.format or _("subsection")).lower() # pylint: disable=no-member if not self._can_user_view_content(course):
if course.self_paced:
# Translators: subsection_format refers to the assignment banner_text = _("Because the course has ended, this assignment is hidden from the learner.")
# type of the subsection, such as Homework, Lab, Exam, etc. else:
banner_text = _( banner_text = _("Because the due date has passed, this assignment is hidden from the learner.")
"Because the due date has passed, "
"this {subsection_format} is hidden from the learner."
).format(subsection_format=subsection_format)
hidden_content_html = self.system.render_template( hidden_content_html = self.system.render_template(
'hidden_content.html', 'hidden_content.html',
{ {
'subsection_format': subsection_format, 'self_paced': course.self_paced,
'progress_url': context.get('progress_url'), 'progress_url': context.get('progress_url'),
} }
) )
...@@ -280,14 +277,15 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -280,14 +277,15 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
if content_milestones and self.runtime.user_is_staff: if content_milestones and self.runtime.user_is_staff:
return banner_text return banner_text
def _can_user_view_content(self): def _can_user_view_content(self, course):
""" """
Returns whether the runtime user can view the content Returns whether the runtime user can view the content
of this sequential. of this sequential.
""" """
hidden_date = course.end if course.self_paced else self.due
return ( return (
self.runtime.user_is_staff or self.runtime.user_is_staff or
self.verify_current_content_visibility(self.due, self.hide_after_due) self.verify_current_content_visibility(hidden_date, self.hide_after_due)
) )
def _student_view(self, context, banner_text=None): def _student_view(self, context, banner_text=None):
......
...@@ -3,49 +3,46 @@ Tests for sequence module. ...@@ -3,49 +3,46 @@ Tests for sequence module.
""" """
# pylint: disable=no-member # pylint: disable=no-member
from datetime import timedelta from datetime import timedelta
import ddt
from django.utils.timezone import now from django.utils.timezone import now
from freezegun import freeze_time from freezegun import freeze_time
from mock import Mock from mock import Mock, patch
from xmodule.seq_module import SequenceModule
from xmodule.tests import get_test_system from xmodule.tests import get_test_system
from xmodule.tests.helpers import StubUserService from xmodule.tests.helpers import StubUserService
from xmodule.tests.xml import XModuleXmlImportTest from xmodule.tests.xml import factories as xml, XModuleXmlImportTest
from xmodule.tests.xml import factories as xml
from xmodule.x_module import STUDENT_VIEW from xmodule.x_module import STUDENT_VIEW
from xmodule.seq_module import SequenceModule
TODAY = now()
DUE_DATE = TODAY + timedelta(days=7)
PAST_DUE_BEFORE_END_DATE = TODAY + timedelta(days=14)
COURSE_END_DATE = TODAY + timedelta(days=21)
@ddt.ddt
class SequenceBlockTestCase(XModuleXmlImportTest): class SequenceBlockTestCase(XModuleXmlImportTest):
""" """
Tests for the Sequence Module. Base class for tests of Sequence Module.
""" """
TODAY = now() def setUp(self):
TOMORROW = TODAY + timedelta(days=1) super(SequenceBlockTestCase, self).setUp()
DAY_AFTER_TOMORROW = TOMORROW + timedelta(days=1)
@classmethod course_xml = self._set_up_course_xml()
def setUpClass(cls): self.course = self.process_xml(course_xml)
super(SequenceBlockTestCase, cls).setUpClass() self._set_up_module_system(self.course)
course_xml = cls._set_up_course_xml() for chapter_index in range(len(self.course.get_children())):
cls.course = cls.process_xml(course_xml) chapter = self._set_up_block(self.course, chapter_index)
cls._set_up_module_system(cls.course) setattr(self, 'chapter_{}'.format(chapter_index + 1), chapter)
for chapter_index in range(len(cls.course.get_children())):
chapter = cls._set_up_block(cls.course, chapter_index)
setattr(cls, 'chapter_{}'.format(chapter_index + 1), chapter)
for sequence_index in range(len(chapter.get_children())): for sequence_index in range(len(chapter.get_children())):
sequence = cls._set_up_block(chapter, sequence_index) sequence = self._set_up_block(chapter, sequence_index)
setattr(cls, 'sequence_{}_{}'.format(chapter_index + 1, sequence_index + 1), sequence) setattr(self, 'sequence_{}_{}'.format(chapter_index + 1, sequence_index + 1), sequence)
@classmethod @staticmethod
def _set_up_course_xml(cls): def _set_up_course_xml():
""" """
Sets up and returns XML course structure. Sets up and returns XML course structure.
""" """
course = xml.CourseFactory.build() course = xml.CourseFactory.build(end=str(COURSE_END_DATE))
chapter_1 = xml.ChapterFactory.build(parent=course) # has 2 child sequences chapter_1 = xml.ChapterFactory.build(parent=course) # has 2 child sequences
xml.ChapterFactory.build(parent=course) # has 0 child sequences xml.ChapterFactory.build(parent=course) # has 0 child sequences
...@@ -58,7 +55,7 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -58,7 +55,7 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
xml.SequenceFactory.build( # sequence_4_1 xml.SequenceFactory.build( # sequence_4_1
parent=chapter_4, parent=chapter_4,
hide_after_due=str(True), hide_after_due=str(True),
due=str(cls.TOMORROW), due=str(DUE_DATE),
) )
for _ in range(3): for _ in range(3):
...@@ -66,14 +63,13 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -66,14 +63,13 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
return course return course
@classmethod def _set_up_block(self, parent, index_in_parent):
def _set_up_block(cls, parent, index_in_parent):
""" """
Sets up the stub sequence module for testing. Sets up the stub sequence module for testing.
""" """
block = parent.get_children()[index_in_parent] block = parent.get_children()[index_in_parent]
cls._set_up_module_system(block) self._set_up_module_system(block)
block.xmodule_runtime._services['bookmarks'] = Mock() # pylint: disable=protected-access block.xmodule_runtime._services['bookmarks'] = Mock() # pylint: disable=protected-access
block.xmodule_runtime._services['user'] = StubUserService() # pylint: disable=protected-access block.xmodule_runtime._services['user'] = StubUserService() # pylint: disable=protected-access
...@@ -81,8 +77,7 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -81,8 +77,7 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
block.parent = parent.location block.parent = parent.location
return block return block
@classmethod def _set_up_module_system(self, block):
def _set_up_module_system(cls, block):
""" """
Sets up the test module system for the given block. Sets up the test module system for the given block.
""" """
...@@ -90,6 +85,28 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -90,6 +85,28 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
module_system.descriptor_runtime = block._runtime # pylint: disable=protected-access module_system.descriptor_runtime = block._runtime # pylint: disable=protected-access
block.xmodule_runtime = module_system block.xmodule_runtime = module_system
def _get_rendered_student_view(self, sequence, requested_child=None, extra_context=None, self_paced=False):
"""
Returns the rendered student view for the given sequence and the
requested_child parameter.
"""
context = {'requested_child': requested_child}
if extra_context:
context.update(extra_context)
# The render operation will ask modulestore for the current course to get some data. As these tests were
# originally not written to be compatible with a real modulestore, we've mocked out the relevant return values.
with patch.object(SequenceModule, '_get_course') as mock_course:
self.course.self_paced = self_paced
mock_course.return_value = self.course
return sequence.xmodule_runtime.render(sequence, STUDENT_VIEW, context).content
def _assert_view_at_position(self, rendered_html, expected_position):
"""
Verifies that the rendered view contains the expected position.
"""
self.assertIn("'position': {}".format(expected_position), rendered_html)
def test_student_view_init(self): def test_student_view_init(self):
seq_module = SequenceModule(runtime=Mock(position=2), descriptor=Mock(), scope_ids=Mock()) seq_module = SequenceModule(runtime=Mock(position=2), descriptor=Mock(), scope_ids=Mock())
self.assertEquals(seq_module.position, 2) # matches position set in the runtime self.assertEquals(seq_module.position, 2) # matches position set in the runtime
...@@ -112,22 +129,6 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -112,22 +129,6 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
html = self._get_rendered_student_view(self.sequence_3_1, requested_child='last') html = self._get_rendered_student_view(self.sequence_3_1, requested_child='last')
self._assert_view_at_position(html, expected_position=3) self._assert_view_at_position(html, expected_position=3)
def _get_rendered_student_view(self, sequence, requested_child=None, extra_context=None):
"""
Returns the rendered student view for the given sequence and the
requested_child parameter.
"""
context = {'requested_child': requested_child}
if extra_context:
context.update(extra_context)
return sequence.xmodule_runtime.render(sequence, STUDENT_VIEW, context).content
def _assert_view_at_position(self, rendered_html, expected_position):
"""
Verifies that the rendered view contains the expected position.
"""
self.assertIn("'position': {}".format(expected_position), rendered_html)
def test_tooltip(self): def test_tooltip(self):
html = self._get_rendered_student_view(self.sequence_3_1, requested_child=None) html = self._get_rendered_student_view(self.sequence_3_1, requested_child=None)
for child in self.sequence_3_1.children: for child in self.sequence_3_1.children:
...@@ -138,26 +139,18 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -138,26 +139,18 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
self.assertIn("seq_module.html", html) self.assertIn("seq_module.html", html)
self.assertIn("'banner_text': None", html) self.assertIn("'banner_text': None", html)
@freeze_time(DAY_AFTER_TOMORROW) @freeze_time(COURSE_END_DATE)
@ddt.data( def test_hidden_content_past_due(self):
(None, 'subsection'),
('Homework', 'homework'),
)
@ddt.unpack
def test_hidden_content_past_due(self, format_type, expected_text):
progress_url = 'http://test_progress_link' progress_url = 'http://test_progress_link'
self._set_sequence_format(self.sequence_4_1, format_type)
html = self._get_rendered_student_view( html = self._get_rendered_student_view(
self.sequence_4_1, self.sequence_4_1,
extra_context=dict(progress_url=progress_url), extra_context=dict(progress_url=progress_url),
) )
self.assertIn("hidden_content.html", html) self.assertIn("hidden_content.html", html)
self.assertIn(progress_url, html) self.assertIn(progress_url, html)
self.assertIn("'subsection_format': '{}'".format(expected_text), html)
@freeze_time(DAY_AFTER_TOMORROW) @freeze_time(COURSE_END_DATE)
def test_masquerade_hidden_content_past_due(self): def test_masquerade_hidden_content_past_due(self):
self._set_sequence_format(self.sequence_4_1, "Homework")
html = self._get_rendered_student_view( html = self._get_rendered_student_view(
self.sequence_4_1, self.sequence_4_1,
extra_context=dict(specific_masquerade=True), extra_context=dict(specific_masquerade=True),
...@@ -165,13 +158,23 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -165,13 +158,23 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
self.assertIn("seq_module.html", html) self.assertIn("seq_module.html", html)
self.assertIn( self.assertIn(
"'banner_text': 'Because the due date has passed, " "'banner_text': 'Because the due date has passed, "
"this homework is hidden from the learner.'", "this assignment is hidden from the learner.'",
html html
) )
def _set_sequence_format(self, sequence, format_type): @freeze_time(PAST_DUE_BEFORE_END_DATE)
""" def test_hidden_content_self_paced_past_due_before_end(self):
Sets the format field on the given sequence to the html = self._get_rendered_student_view(self.sequence_4_1, self_paced=True)
given value. self.assertIn("seq_module.html", html)
""" self.assertIn("'banner_text': None", html)
sequence._xmodule.format = format_type # pylint: disable=protected-access
@freeze_time(COURSE_END_DATE + timedelta(days=7))
def test_hidden_content_self_paced_past_end(self):
progress_url = 'http://test_progress_link'
html = self._get_rendered_student_view(
self.sequence_4_1,
extra_context=dict(progress_url=progress_url),
self_paced=True,
)
self.assertIn("hidden_content.html", html)
self.assertIn(progress_url, html)
...@@ -209,13 +209,13 @@ class CoursewarePage(CoursePage): ...@@ -209,13 +209,13 @@ class CoursewarePage(CoursePage):
""" """
return self.q(css="div.proctored-exam.completed").visible return self.q(css="div.proctored-exam.completed").visible
def content_hidden_past_due_date(self, content_type="subsection"): def content_hidden_past_due_date(self):
""" """
Returns whether the "the due date for this ___ has passed" message is present. Returns whether the "the due date for this ___ has passed" message is present.
___ is the type of the hidden content, and defaults to subsection. ___ is the type of the hidden content, and defaults to subsection.
This being true implies "the ___ contents are hidden because their due date has passed". This being true implies "the ___ contents are hidden because their due date has passed".
""" """
message = "The due date for this {0} has passed.".format(content_type) message = "this assignment is no longer available"
if self.q(css="div.seq_content").is_present(): if self.q(css="div.seq_content").is_present():
return False return False
for html in self.q(css="div.hidden-content").html: for html in self.q(css="div.hidden-content").html:
......
...@@ -25,7 +25,7 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor ...@@ -25,7 +25,7 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor
Staff users are exempted from hidden content rules. Staff users are exempted from hidden content rules.
""" """
VERSION = 1 VERSION = 2
MERGED_DUE_DATE = 'merged_due_date' MERGED_DUE_DATE = 'merged_due_date'
MERGED_HIDE_AFTER_DUE = 'merged_hide_after_due' MERGED_HIDE_AFTER_DUE = 'merged_hide_after_due'
...@@ -41,7 +41,7 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor ...@@ -41,7 +41,7 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor
def _get_merged_hide_after_due(cls, block_structure, block_key): def _get_merged_hide_after_due(cls, block_structure, block_key):
""" """
Returns whether the block with the given block_key in the Returns whether the block with the given block_key in the
given block_structure should be visible to staff only per given block_structure should be hidden after due date per
computed value from ancestry chain. computed value from ancestry chain.
""" """
return block_structure.get_transformer_block_field( return block_structure.get_transformer_block_field(
...@@ -81,6 +81,8 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor ...@@ -81,6 +81,8 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor
func_merge_ancestors=min, func_merge_ancestors=min,
) )
block_structure.request_xblock_fields(u'self_paced', u'end')
def transform_block_filters(self, usage_info, block_structure): def transform_block_filters(self, usage_info, block_structure):
# Users with staff access bypass the Visibility check. # Users with staff access bypass the Visibility check.
if usage_info.has_staff_access: if usage_info.has_staff_access:
...@@ -97,6 +99,10 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor ...@@ -97,6 +99,10 @@ class HiddenContentTransformer(FilteringTransformerMixin, BlockStructureTransfor
Returns whether the block with the given block_key should Returns whether the block with the given block_key should
be hidden, given the current time. be hidden, given the current time.
""" """
due = self._get_merged_due_date(block_structure, block_key)
hide_after_due = self._get_merged_hide_after_due(block_structure, block_key) hide_after_due = self._get_merged_hide_after_due(block_structure, block_key)
return not SequenceModule.verify_current_content_visibility(due, hide_after_due) self_paced = block_structure[block_structure.root_block_usage_key].self_paced
if self_paced:
hidden_date = block_structure[block_structure.root_block_usage_key].end
else:
hidden_date = self._get_merged_due_date(block_structure, block_key)
return not SequenceModule.verify_current_content_visibility(hidden_date, hide_after_due)
...@@ -199,7 +199,7 @@ class IndexQueryTestCase(ModuleStoreTestCase): ...@@ -199,7 +199,7 @@ class IndexQueryTestCase(ModuleStoreTestCase):
NUM_PROBLEMS = 20 NUM_PROBLEMS = 20
@ddt.data( @ddt.data(
(ModuleStoreEnum.Type.mongo, 8), (ModuleStoreEnum.Type.mongo, 9),
(ModuleStoreEnum.Type.split, 4), (ModuleStoreEnum.Type.split, 4),
) )
@ddt.unpack @ddt.unpack
......
...@@ -4,15 +4,14 @@ Grades related signals. ...@@ -4,15 +4,14 @@ Grades related signals.
from logging import getLogger from logging import getLogger
from courseware.model_data import get_score, set_score
from django.dispatch import receiver from django.dispatch import receiver
from openedx.core.lib.grade_utils import is_score_higher
from submissions.models import score_set, score_reset from submissions.models import score_set, score_reset
from util.date_utils import to_timestamp
from courseware.model_data import get_score, set_score from courseware.model_data import get_score, set_score
from eventtracking import tracker from eventtracking import tracker
from openedx.core.lib.grade_utils import is_score_higher
from student.models import user_by_anonymous_id from student.models import user_by_anonymous_id
from util.date_utils import to_timestamp
from track.event_transaction_utils import ( from track.event_transaction_utils import (
get_event_transaction_type, get_event_transaction_type,
get_event_transaction_id, get_event_transaction_id,
......
...@@ -11,6 +11,7 @@ from logging import getLogger ...@@ -11,6 +11,7 @@ from logging import getLogger
from courseware.model_data import get_score from courseware.model_data import get_score
from lms.djangoapps.course_blocks.api import get_course_blocks from lms.djangoapps.course_blocks.api import get_course_blocks
from openedx.core.djangoapps.celery_utils.task import PersistOnFailureTask
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.locator import CourseLocator from opaque_keys.edx.locator import CourseLocator
from submissions import api as sub_api from submissions import api as sub_api
...@@ -54,7 +55,7 @@ def recalculate_subsection_grade( ...@@ -54,7 +55,7 @@ def recalculate_subsection_grade(
) )
@task(default_retry_delay=30, routing_key=settings.RECALCULATE_GRADES_ROUTING_KEY) @task(base=PersistOnFailureTask, default_retry_delay=30, routing_key=settings.RECALCULATE_GRADES_ROUTING_KEY)
def recalculate_subsection_grade_v2(**kwargs): def recalculate_subsection_grade_v2(**kwargs):
""" """
Updates a saved subsection grade. Updates a saved subsection grade.
......
...@@ -2153,6 +2153,10 @@ INSTALLED_APPS = ( ...@@ -2153,6 +2153,10 @@ INSTALLED_APPS = (
# additional release utilities to ease automation # additional release utilities to ease automation
'release_util', 'release_util',
# Customized celery tasks, including persisting failed tasks so they can
# be retried
'openedx.core.djangoapps.celery_utils',
) )
# Migrations which are not in the standard module "migrations" # Migrations which are not in the standard module "migrations"
......
...@@ -5,22 +5,35 @@ from openedx.core.djangolib.markup import HTML, Text ...@@ -5,22 +5,35 @@ from openedx.core.djangolib.markup import HTML, Text
%> %>
<div class="sequence hidden-content proctored-exam completed"> <div class="sequence hidden-content proctored-exam completed">
<h3> <h3>
${_("The due date for this {subsection_format} has passed.").format( % if self_paced:
subsection_format=subsection_format, ${_("The course has ended.")}
)} % else:
</h3> ${_("The due date for this assignment has passed.")}
<hr> % endif
<p> </h3>
${Text(_( <hr>
"Because the due date has passed, this {subsection_format} " <p>
"is no longer available.{line_break}If you have completed this {subsection_format}, " % if self_paced:
"your grade is available on the {link_start}progress page{link_end}." ${Text(_(
)).format( "Because the course has ended, this assignment is no longer "
subsection_format=subsection_format, "available.{line_break}If you have completed this assignment, your "
line_break=HTML("<br>"), "grade is available on the {link_start}progress page{link_end}."
link_start=HTML("<a href='{}'>").format(progress_url), )).format(
link_end=HTML("</a>"), line_break=HTML("<br>"),
)} link_start=HTML("<a href='{}'>").format(progress_url),
</p> link_end=HTML("</a>"),
)}
% else:
${Text(_(
"Because the due date has passed, this assignment is no longer "
"available.{line_break}If you have completed this assignment, your "
"grade is available on the {link_start}progress page{link_end}."
)).format(
line_break=HTML("<br>"),
link_start=HTML("<a href='{}'>").format(progress_url),
link_end=HTML("</a>"),
)}
% endif
</p>
</div> </div>
#pylint: disable=missing-docstring #pylint: disable=missing-docstring
import unittest
import ddt import ddt
from django.conf import settings
from django.test import TestCase from django.test import TestCase
from openedx.core.djangoapps.api_admin.forms import ApiAccessRequestForm from openedx.core.djangoapps.api_admin.forms import ApiAccessRequestForm
from openedx.core.djangoapps.api_admin.tests.utils import VALID_DATA from openedx.core.djangoapps.api_admin.tests.utils import VALID_DATA
from openedx.core.djangolib.testing.utils import skip_unless_lms
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@ddt.ddt @ddt.ddt
class ApiAccessFormTest(TestCase): class ApiAccessFormTest(TestCase):
......
...@@ -2,21 +2,20 @@ ...@@ -2,21 +2,20 @@
from smtplib import SMTPException from smtplib import SMTPException
import ddt import ddt
from django.conf import settings
from django.db import IntegrityError from django.db import IntegrityError
from django.test import TestCase from django.test import TestCase
import mock import mock
import unittest
from microsite_configuration.tests.factories import SiteFactory from microsite_configuration.tests.factories import SiteFactory
from openedx.core.djangoapps.api_admin.models import ApiAccessRequest, ApiAccessConfig from openedx.core.djangoapps.api_admin.models import ApiAccessRequest, ApiAccessConfig
from openedx.core.djangoapps.api_admin.models import log as model_log from openedx.core.djangoapps.api_admin.models import log as model_log
from openedx.core.djangoapps.api_admin.tests.factories import ApiAccessRequestFactory from openedx.core.djangoapps.api_admin.tests.factories import ApiAccessRequestFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class ApiAccessRequestTests(TestCase): class ApiAccessRequestTests(TestCase):
def setUp(self): def setUp(self):
...@@ -79,7 +78,7 @@ class ApiAccessConfigTests(TestCase): ...@@ -79,7 +78,7 @@ class ApiAccessConfigTests(TestCase):
) )
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class ApiAccessRequestSignalTests(TestCase): class ApiAccessRequestSignalTests(TestCase):
def setUp(self): def setUp(self):
super(ApiAccessRequestSignalTests, self).setUp() super(ApiAccessRequestSignalTests, self).setUp()
......
""" Tests for the api_admin app's views. """ """ Tests for the api_admin app's views. """
import json import json
import unittest
import ddt import ddt
import httpretty import httpretty
...@@ -16,19 +15,26 @@ from openedx.core.djangoapps.api_admin.tests.factories import ( ...@@ -16,19 +15,26 @@ from openedx.core.djangoapps.api_admin.tests.factories import (
ApiAccessRequestFactory, ApplicationFactory, CatalogFactory ApiAccessRequestFactory, ApplicationFactory, CatalogFactory
) )
from openedx.core.djangoapps.api_admin.tests.utils import VALID_DATA from openedx.core.djangoapps.api_admin.tests.utils import VALID_DATA
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
Application = get_application_model() # pylint: disable=invalid-name Application = get_application_model() # pylint: disable=invalid-name
class ApiAdminTest(TestCase): class ApiAdminTest(TestCase):
"""
Base class to allow API admin access to tests.
"""
def setUp(self): def setUp(self):
super(ApiAdminTest, self).setUp() super(ApiAdminTest, self).setUp()
ApiAccessConfig(enabled=True).save() ApiAccessConfig(enabled=True).save()
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class ApiRequestViewTest(ApiAdminTest): class ApiRequestViewTest(ApiAdminTest):
"""
Test the API Request View.
"""
def setUp(self): def setUp(self):
super(ApiRequestViewTest, self).setUp() super(ApiRequestViewTest, self).setUp()
self.url = reverse('api_admin:api-request') self.url = reverse('api_admin:api-request')
...@@ -93,10 +99,13 @@ class ApiRequestViewTest(ApiAdminTest): ...@@ -93,10 +99,13 @@ class ApiRequestViewTest(ApiAdminTest):
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(PLATFORM_NAME='edX') @override_settings(PLATFORM_NAME='edX')
@ddt.ddt @ddt.ddt
class ApiRequestStatusViewTest(ApiAdminTest): class ApiRequestStatusViewTest(ApiAdminTest):
"""
Tests of the API Status endpoint.
"""
def setUp(self): def setUp(self):
super(ApiRequestStatusViewTest, self).setUp() super(ApiRequestStatusViewTest, self).setUp()
password = 'abc123' password = 'abc123'
...@@ -198,10 +207,15 @@ class ApiRequestStatusViewTest(ApiAdminTest): ...@@ -198,10 +207,15 @@ class ApiRequestStatusViewTest(ApiAdminTest):
self.assertIn('Enter a valid URL.', response.content) self.assertIn('Enter a valid URL.', response.content)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class ApiTosViewTest(ApiAdminTest): class ApiTosViewTest(ApiAdminTest):
"""
Tests of the API terms of service endpoint.
"""
def test_get_api_tos(self): def test_get_api_tos(self):
"""Verify that the terms of service can be read.""" """
Verify that the terms of service can be read.
"""
url = reverse('api_admin:api-tos') url = reverse('api_admin:api-tos')
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
...@@ -209,6 +223,9 @@ class ApiTosViewTest(ApiAdminTest): ...@@ -209,6 +223,9 @@ class ApiTosViewTest(ApiAdminTest):
class CatalogTest(ApiAdminTest): class CatalogTest(ApiAdminTest):
"""
Test the catalog API.
"""
def setUp(self): def setUp(self):
super(CatalogTest, self).setUp() super(CatalogTest, self).setUp()
password = 'abc123' password = 'abc123'
...@@ -232,8 +249,11 @@ class CatalogTest(ApiAdminTest): ...@@ -232,8 +249,11 @@ class CatalogTest(ApiAdminTest):
) )
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CatalogSearchViewTest(CatalogTest): class CatalogSearchViewTest(CatalogTest):
"""
Test the catalog search endpoint.
"""
def setUp(self): def setUp(self):
super(CatalogSearchViewTest, self).setUp() super(CatalogSearchViewTest, self).setUp()
self.url = reverse('api_admin:catalog-search') self.url = reverse('api_admin:catalog-search')
...@@ -254,8 +274,11 @@ class CatalogSearchViewTest(CatalogTest): ...@@ -254,8 +274,11 @@ class CatalogSearchViewTest(CatalogTest):
self.assertRedirects(response, reverse('api_admin:catalog-search')) self.assertRedirects(response, reverse('api_admin:catalog-search'))
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CatalogListViewTest(CatalogTest): class CatalogListViewTest(CatalogTest):
"""
Test the catalog list endpoint.
"""
def setUp(self): def setUp(self):
super(CatalogListViewTest, self).setUp() super(CatalogListViewTest, self).setUp()
self.catalog_user = UserFactory() self.catalog_user = UserFactory()
...@@ -304,8 +327,11 @@ class CatalogListViewTest(CatalogTest): ...@@ -304,8 +327,11 @@ class CatalogListViewTest(CatalogTest):
self.assertEqual(len([r for r in httpretty.httpretty.latest_requests if r.method == 'POST']), 0) self.assertEqual(len([r for r in httpretty.httpretty.latest_requests if r.method == 'POST']), 0)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CatalogEditViewTest(CatalogTest): class CatalogEditViewTest(CatalogTest):
"""
Test edits to the catalog endpoint.
"""
def setUp(self): def setUp(self):
super(CatalogEditViewTest, self).setUp() super(CatalogEditViewTest, self).setUp()
self.catalog_user = UserFactory() self.catalog_user = UserFactory()
...@@ -353,8 +379,11 @@ class CatalogEditViewTest(CatalogTest): ...@@ -353,8 +379,11 @@ class CatalogEditViewTest(CatalogTest):
self.assertEqual(len([r for r in httpretty.httpretty.latest_requests if r.method == 'PATCH']), 0) self.assertEqual(len([r for r in httpretty.httpretty.latest_requests if r.method == 'PATCH']), 0)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CatalogPreviewViewTest(CatalogTest): class CatalogPreviewViewTest(CatalogTest):
"""
Test the catalog preview endpoint.
"""
def setUp(self): def setUp(self):
super(CatalogPreviewViewTest, self).setUp() super(CatalogPreviewViewTest, self).setUp()
self.url = reverse('api_admin:catalog-preview') self.url = reverse('api_admin:catalog-preview')
......
...@@ -4,13 +4,13 @@ Tests for bookmarks api. ...@@ -4,13 +4,13 @@ Tests for bookmarks api.
import ddt import ddt
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from unittest import skipUnless
from django.conf import settings from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from openedx.core.djangolib.testing.utils import skip_unless_lms
from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.exceptions import ItemNotFoundError
from .. import api from .. import api
...@@ -38,7 +38,7 @@ class BookmarkApiEventTestMixin(object): ...@@ -38,7 +38,7 @@ class BookmarkApiEventTestMixin(object):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') @skip_unless_lms
class BookmarksAPITests(BookmarkApiEventTestMixin, BookmarksTestsBase): class BookmarksAPITests(BookmarkApiEventTestMixin, BookmarksTestsBase):
""" """
These tests cover the parts of the API methods. These tests cover the parts of the API methods.
......
...@@ -8,9 +8,6 @@ from freezegun import freeze_time ...@@ -8,9 +8,6 @@ from freezegun import freeze_time
import mock import mock
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
import pytz import pytz
from unittest import skipUnless
from django.conf import settings
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.locator import CourseLocator, BlockUsageLocator from opaque_keys.edx.locator import CourseLocator, BlockUsageLocator
...@@ -19,6 +16,7 @@ from xmodule.modulestore.django import modulestore ...@@ -19,6 +16,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.factories import check_mongo_calls, CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import check_mongo_calls, CourseFactory, ItemFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import AdminFactory, UserFactory from student.tests.factories import AdminFactory, UserFactory
from .. import DEFAULT_FIELDS, OPTIONAL_FIELDS, PathItem from .. import DEFAULT_FIELDS, OPTIONAL_FIELDS, PathItem
...@@ -228,7 +226,7 @@ class BookmarksTestsBase(ModuleStoreTestCase): ...@@ -228,7 +226,7 @@ class BookmarksTestsBase(ModuleStoreTestCase):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') @skip_unless_lms
class BookmarkModelTests(BookmarksTestsBase): class BookmarkModelTests(BookmarksTestsBase):
""" """
Test the Bookmark model. Test the Bookmark model.
......
...@@ -2,18 +2,16 @@ ...@@ -2,18 +2,16 @@
Tests for bookmark services. Tests for bookmark services.
""" """
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from unittest import skipUnless
from django.conf import settings
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ..services import BookmarksService from ..services import BookmarksService
from .test_models import BookmarksTestsBase from .test_models import BookmarksTestsBase
@attr(shard=2) @attr(shard=2)
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') @skip_unless_lms
class BookmarksServiceTests(BookmarksTestsBase): class BookmarksServiceTests(BookmarksTestsBase):
""" """
Tests the Bookmarks service. Tests the Bookmarks service.
......
...@@ -5,7 +5,6 @@ Tests for bookmark views. ...@@ -5,7 +5,6 @@ Tests for bookmark views.
import ddt import ddt
import json import json
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from unittest import skipUnless
import urllib import urllib
from django.conf import settings from django.conf import settings
...@@ -13,6 +12,7 @@ from django.core.urlresolvers import reverse ...@@ -13,6 +12,7 @@ from django.core.urlresolvers import reverse
from mock import patch from mock import patch
from rest_framework.test import APIClient from rest_framework.test import APIClient
from openedx.core.djangolib.testing.utils import skip_unless_lms
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from .test_models import BookmarksTestsBase from .test_models import BookmarksTestsBase
...@@ -66,7 +66,7 @@ class BookmarksViewsTestsBase(BookmarksTestsBase, BookmarkApiEventTestMixin): ...@@ -66,7 +66,7 @@ class BookmarksViewsTestsBase(BookmarksTestsBase, BookmarkApiEventTestMixin):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') @skip_unless_lms
class BookmarksListViewTests(BookmarksViewsTestsBase): class BookmarksListViewTests(BookmarksViewsTestsBase):
""" """
This contains the tests for GET & POST methods of bookmark.views.BookmarksListView class This contains the tests for GET & POST methods of bookmark.views.BookmarksListView class
...@@ -371,7 +371,7 @@ class BookmarksListViewTests(BookmarksViewsTestsBase): ...@@ -371,7 +371,7 @@ class BookmarksListViewTests(BookmarksViewsTestsBase):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') @skip_unless_lms
class BookmarksDetailViewTests(BookmarksViewsTestsBase): class BookmarksDetailViewTests(BookmarksViewsTestsBase):
""" """
This contains the tests for GET & DELETE methods of bookmark.views.BookmarksDetailView class This contains the tests for GET & DELETE methods of bookmark.views.BookmarksDetailView class
......
"""Tests for cached authentication middleware.""" """Tests for cached authentication middleware."""
import unittest
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
from mock import patch from mock import patch
from openedx.core.djangolib.testing.utils import skip_unless_cms, skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
...@@ -33,13 +31,13 @@ class CachedAuthMiddlewareTestCase(TestCase): ...@@ -33,13 +31,13 @@ class CachedAuthMiddlewareTestCase(TestCase):
response = self.client.get(test_url) response = self.client.get(test_url)
self.assertRedirects(response, redirect_url) self.assertRedirects(response, redirect_url)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
def test_session_change_lms(self): def test_session_change_lms(self):
"""Test session verification with LMS-specific URLs.""" """Test session verification with LMS-specific URLs."""
dashboard_url = reverse('dashboard') dashboard_url = reverse('dashboard')
self._test_change_session_hash(dashboard_url, reverse('signin_user') + '?next=' + dashboard_url) self._test_change_session_hash(dashboard_url, reverse('signin_user') + '?next=' + dashboard_url)
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
def test_session_change_cms(self): def test_session_change_cms(self):
"""Test session verification with CMS-specific URLs.""" """Test session verification with CMS-specific URLs."""
home_url = reverse('home') home_url = reverse('home')
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
import jsonfield.fields
import model_utils.fields
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='FailedTask',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)),
('task_name', models.CharField(max_length=255)),
('task_id', models.CharField(max_length=255, db_index=True)),
('args', jsonfield.fields.JSONField(blank=True)),
('kwargs', jsonfield.fields.JSONField(blank=True)),
('exc', models.CharField(max_length=255)),
('datetime_resolved', models.DateTimeField(default=None, null=True, db_index=True, blank=True)),
],
),
migrations.AlterIndexTogether(
name='failedtask',
index_together=set([('task_name', 'exc')]),
),
]
"""
Models to support persistent tasks.
"""
from django.db import models
from jsonfield import JSONField
from model_utils.models import TimeStampedModel
class FailedTask(TimeStampedModel):
"""
Representation of tasks that have failed
"""
task_name = models.CharField(max_length=255)
task_id = models.CharField(max_length=255, db_index=True)
args = JSONField(blank=True)
kwargs = JSONField(blank=True)
exc = models.CharField(max_length=255)
datetime_resolved = models.DateTimeField(blank=True, null=True, default=None, db_index=True)
class Meta(object):
index_together = [
(u'task_name', u'exc'),
]
def __unicode__(self):
return u'FailedTask: {task_name}, args={args}, kwargs={kwargs} ({resolution})'.format(
task_name=self.task_name,
args=self.args,
kwargs=self.kwargs,
resolution=u"not resolved" if self.datetime_resolved is None else "resolved"
)
"""
Celery utility code for persistent tasks.
"""
from celery import Task
from .models import FailedTask
# pylint: disable=abstract-method
class PersistOnFailureTask(Task):
"""
Custom Celery Task base class that persists task data on failure.
"""
def on_failure(self, exc, task_id, args, kwargs, einfo):
"""
If the task fails, persist a record of the task.
"""
FailedTask.objects.create(
task_name=_truncate_to_field(FailedTask, 'task_name', self.name),
task_id=task_id, # Fixed length UUID: No need to truncate
args=args,
kwargs=kwargs,
exc=_truncate_to_field(FailedTask, 'exc', repr(exc)),
)
super(PersistOnFailureTask, self).on_failure(exc, task_id, args, kwargs, einfo)
def _truncate_to_field(model, field_name, value):
"""
If data is too big for the field, it would cause a failure to
insert, so we shorten it, truncating in the middle (because
valuable information often shows up at the end.
"""
field = model._meta.get_field(field_name) # pylint: disable=protected-access
if len(value) > field.max_length:
midpoint = field.max_length // 2
len_after_midpoint = field.max_length - midpoint
first = value[:midpoint]
sep = u'...'
last = value[len(value) - len_after_midpoint + len(sep):]
value = sep.join([first, last])
return value
u"""
Testing persistent tasks
"""
from __future__ import print_function
from celery import task
from django.test import TestCase
import six
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ..models import FailedTask
from ..task import PersistOnFailureTask
@skip_unless_lms
class PersistOnFailureTaskTestCase(TestCase):
"""
Test that persistent tasks save the appropriate values when needed.
"""
@classmethod
def setUpClass(cls):
@task(base=PersistOnFailureTask)
def exampletask(message=None):
u"""
A simple task for testing persistence
"""
if message:
raise ValueError(message)
return
cls.exampletask = exampletask
super(PersistOnFailureTaskTestCase, cls).setUpClass()
def test_exampletask_without_failure(self):
result = self.exampletask.delay()
result.wait()
self.assertEqual(result.status, u'SUCCESS')
self.assertFalse(FailedTask.objects.exists())
def test_exampletask_with_failure(self):
result = self.exampletask.delay(message=u'The example task failed')
with self.assertRaises(ValueError):
result.wait()
self.assertEqual(result.status, u'FAILURE')
failed_task_object = FailedTask.objects.get()
# Assert that we get the kind of data we expect
self.assertEqual(
failed_task_object.task_name,
u'openedx.core.djangoapps.celery_utils.tests.test_task.exampletask'
)
self.assertEqual(failed_task_object.args, [])
self.assertEqual(failed_task_object.kwargs, {u'message': u'The example task failed'})
self.assertEqual(failed_task_object.exc, u"ValueError(u'The example task failed',)")
self.assertIsNone(failed_task_object.datetime_resolved)
def test_persists_when_called_with_wrong_args(self):
result = self.exampletask.delay(15, u'2001-03-04', err=True)
with self.assertRaises(TypeError):
result.wait()
self.assertEqual(result.status, u'FAILURE')
failed_task_object = FailedTask.objects.get()
self.assertEqual(failed_task_object.args, [15, u'2001-03-04'])
self.assertEqual(failed_task_object.kwargs, {u'err': True})
def test_persists_with_overlength_field(self):
overlong_message = u''.join(u'%03d' % x for x in six.moves.range(100))
result = self.exampletask.delay(message=overlong_message)
with self.assertRaises(ValueError):
result.wait()
failed_task_object = FailedTask.objects.get()
# Length is max field length
self.assertEqual(len(failed_task_object.exc), 255)
# Ellipses are put in the middle
self.assertEqual(u'037...590', failed_task_object.exc[124:133])
# The beginning of the input is captured
self.assertEqual(failed_task_object.exc[:11], u"ValueError(")
# The end of the input is captured
self.assertEqual(failed_task_object.exc[-9:], u"098099',)")
...@@ -2,13 +2,9 @@ ...@@ -2,13 +2,9 @@
Test the partitions and partitions service Test the partitions and partitions service
""" """
import json
from django.conf import settings
import django.test import django.test
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from unittest import skipUnless
from courseware.masquerade import handle_ajax, setup_masquerade from courseware.masquerade import handle_ajax, setup_masquerade
from courseware.tests.test_masquerade import StaffMasqueradeTestCase from courseware.tests.test_masquerade import StaffMasqueradeTestCase
...@@ -19,6 +15,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DAT ...@@ -19,6 +15,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DAT
from xmodule.modulestore.tests.factories import ToyCourseFactory from xmodule.modulestore.tests.factories import ToyCourseFactory
from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ..partition_scheme import CohortPartitionScheme, get_cohorted_user_partition from ..partition_scheme import CohortPartitionScheme, get_cohorted_user_partition
from ..models import CourseUserGroupPartitionGroup from ..models import CourseUserGroupPartitionGroup
from ..views import link_cohort_to_partition_group, unlink_cohort_partition_group from ..views import link_cohort_to_partition_group, unlink_cohort_partition_group
...@@ -383,7 +380,7 @@ class TestMasqueradedGroup(StaffMasqueradeTestCase): ...@@ -383,7 +380,7 @@ class TestMasqueradedGroup(StaffMasqueradeTestCase):
self._verify_masquerade_for_group(self.user_partition.groups[1]) self._verify_masquerade_for_group(self.user_partition.groups[1])
self._verify_masquerade_for_group(None) self._verify_masquerade_for_group(None)
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False}) @patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_group_masquerade(self): def test_group_masquerade(self):
""" """
...@@ -391,7 +388,7 @@ class TestMasqueradedGroup(StaffMasqueradeTestCase): ...@@ -391,7 +388,7 @@ class TestMasqueradedGroup(StaffMasqueradeTestCase):
""" """
self._verify_masquerade_for_all_groups() self._verify_masquerade_for_all_groups()
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False}) @patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
def test_group_masquerade_with_cohort(self): def test_group_masquerade_with_cohort(self):
""" """
......
...@@ -8,9 +8,7 @@ import json ...@@ -8,9 +8,7 @@ import json
from collections import namedtuple from collections import namedtuple
from datetime import datetime from datetime import datetime
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from unittest import skipUnless
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.http import Http404 from django.http import Http404
from django.test.client import RequestFactory from django.test.client import RequestFactory
...@@ -22,6 +20,8 @@ from xmodule.modulestore.tests.factories import CourseFactory ...@@ -22,6 +20,8 @@ from xmodule.modulestore.tests.factories import CourseFactory
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.tests.factories import ItemFactory from xmodule.modulestore.tests.factories import ItemFactory
from lms.djangoapps.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY from lms.djangoapps.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ..models import CourseUserGroup, CourseCohort from ..models import CourseUserGroup, CourseCohort
from ..views import ( from ..views import (
...@@ -1207,7 +1207,7 @@ class RemoveUserFromCohortTestCase(CohortViewsTestCase): ...@@ -1207,7 +1207,7 @@ class RemoveUserFromCohortTestCase(CohortViewsTestCase):
@attr(shard=2) @attr(shard=2)
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') @skip_unless_lms
class CourseCohortDiscussionTopicsTestCase(CohortViewsTestCase): class CourseCohortDiscussionTopicsTestCase(CohortViewsTestCase):
""" """
Tests the `cohort_discussion_topics` view. Tests the `cohort_discussion_topics` view.
......
""" CourseTalk widget helpers tests """ """ CourseTalk widget helpers tests """
from __future__ import unicode_literals from __future__ import unicode_literals
from unittest import skipUnless
from django import test from django import test
from django.conf import settings
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from openedx.core.djangoapps.coursetalk import helpers from openedx.core.djangoapps.coursetalk import helpers
from openedx.core.djangoapps.coursetalk import models from openedx.core.djangoapps.coursetalk import models
from openedx.core.djangolib.testing.utils import skip_unless_lms
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') @skip_unless_lms
class CourseTalkKeyTests(test.TestCase): class CourseTalkKeyTests(test.TestCase):
""" """
CourseTalkKeyTests: CourseTalkKeyTests:
......
"""Tests for models supporting Credentials-related functionality.""" """Tests for models supporting Credentials-related functionality."""
import unittest
from django.conf import settings
from django.test import TestCase from django.test import TestCase
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin
from openedx.core.djangolib.testing.utils import skip_unless_lms
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@attr(shard=2) @attr(shard=2)
class TestCredentialsApiConfig(CredentialsApiConfigMixin, TestCase): class TestCredentialsApiConfig(CredentialsApiConfigMixin, TestCase):
"""Tests covering the CredentialsApiConfig model.""" """Tests covering the CredentialsApiConfig model."""
......
"""Tests covering Credentials utilities.""" """Tests covering Credentials utilities."""
import unittest
from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
import httpretty import httpretty
...@@ -18,11 +15,11 @@ from openedx.core.djangoapps.credentials.utils import ( ...@@ -18,11 +15,11 @@ from openedx.core.djangoapps.credentials.utils import (
from openedx.core.djangoapps.credentials.tests import factories from openedx.core.djangoapps.credentials.tests import factories
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin
from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@attr(shard=2) @attr(shard=2)
class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin, CredentialsDataMixin, class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin, CredentialsDataMixin,
ProgramsDataMixin, CacheIsolationTestCase): ProgramsDataMixin, CacheIsolationTestCase):
......
...@@ -3,10 +3,8 @@ Tests for the API functions in the credit app. ...@@ -3,10 +3,8 @@ Tests for the API functions in the credit app.
""" """
import datetime import datetime
import json import json
import unittest
import ddt import ddt
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core import mail from django.core import mail
from django.test.utils import override_settings from django.test.utils import override_settings
...@@ -36,6 +34,7 @@ from openedx.core.djangoapps.credit.models import ( ...@@ -36,6 +34,7 @@ from openedx.core.djangoapps.credit.models import (
CreditEligibility, CreditEligibility,
CreditRequest CreditRequest
) )
from openedx.core.djangolib.testing.utils import skip_unless_lms
from course_modes.models import CourseMode from course_modes.models import CourseMode
from student.models import CourseEnrollment from student.models import CourseEnrollment
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
...@@ -203,7 +202,7 @@ class CreditApiTestBase(ModuleStoreTestCase): ...@@ -203,7 +202,7 @@ class CreditApiTestBase(ModuleStoreTestCase):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
@ddt.ddt @ddt.ddt
class CreditRequirementApiTests(CreditApiTestBase): class CreditRequirementApiTests(CreditApiTestBase):
""" """
...@@ -1165,7 +1164,7 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase): ...@@ -1165,7 +1164,7 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
@override_settings( @override_settings(
ECOMMERCE_API_URL=TEST_API_URL, ECOMMERCE_API_URL=TEST_API_URL,
ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY, ECOMMERCE_API_SIGNING_KEY=TEST_API_SIGNING_KEY,
......
...@@ -5,9 +5,6 @@ Tests for In-Course Reverification Access Control Partition scheme ...@@ -5,9 +5,6 @@ Tests for In-Course Reverification Access Control Partition scheme
import ddt import ddt
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
import unittest
from django.conf import settings
from lms.djangoapps.verify_student.models import ( from lms.djangoapps.verify_student.models import (
VerificationCheckpoint, VerificationCheckpoint,
...@@ -15,6 +12,7 @@ from lms.djangoapps.verify_student.models import ( ...@@ -15,6 +12,7 @@ from lms.djangoapps.verify_student.models import (
SkippedReverification, SkippedReverification,
) )
from openedx.core.djangoapps.credit.partition_schemes import VerificationPartitionScheme from openedx.core.djangoapps.credit.partition_schemes import VerificationPartitionScheme
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.models import CourseEnrollment from student.models import CourseEnrollment
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.partitions.partitions import UserPartition, Group from xmodule.partitions.partitions import UserPartition, Group
...@@ -24,7 +22,7 @@ from xmodule.modulestore.tests.factories import CourseFactory ...@@ -24,7 +22,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class ReverificationPartitionTest(ModuleStoreTestCase): class ReverificationPartitionTest(ModuleStoreTestCase):
"""Tests for the Reverification Partition Scheme. """ """Tests for the Reverification Partition Scheme. """
......
...@@ -6,9 +6,7 @@ import ddt ...@@ -6,9 +6,7 @@ import ddt
import pytz import pytz
from datetime import timedelta, datetime from datetime import timedelta, datetime
from mock import MagicMock from mock import MagicMock
from unittest import skipUnless
from django.conf import settings
from django.test.client import RequestFactory from django.test.client import RequestFactory
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from course_modes.models import CourseMode from course_modes.models import CourseMode
...@@ -22,10 +20,11 @@ from openedx.core.djangoapps.credit.api import ( ...@@ -22,10 +20,11 @@ from openedx.core.djangoapps.credit.api import (
) )
from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider
from openedx.core.djangoapps.credit.signals import listen_for_grade_calculation from openedx.core.djangoapps.credit.signals import listen_for_grade_calculation
from openedx.core.djangolib.testing.utils import skip_unless_lms
@attr(shard=2) @attr(shard=2)
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
@ddt.ddt @ddt.ddt
class TestMinGradedRequirementStatus(ModuleStoreTestCase): class TestMinGradedRequirementStatus(ModuleStoreTestCase):
"""Test cases to check the minimum grade requirement status updated. """Test cases to check the minimum grade requirement status updated.
......
...@@ -8,7 +8,6 @@ from __future__ import unicode_literals ...@@ -8,7 +8,6 @@ from __future__ import unicode_literals
import datetime import datetime
import json import json
import unittest
import ddt import ddt
import pytz import pytz
...@@ -28,6 +27,7 @@ from openedx.core.djangoapps.credit.signature import signature ...@@ -28,6 +27,7 @@ from openedx.core.djangoapps.credit.signature import signature
from openedx.core.djangoapps.credit.tests.factories import ( from openedx.core.djangoapps.credit.tests.factories import (
CreditProviderFactory, CreditEligibilityFactory, CreditCourseFactory, CreditRequestFactory, CreditProviderFactory, CreditEligibilityFactory, CreditCourseFactory, CreditRequestFactory,
) )
from openedx.core.djangolib.testing.utils import skip_unless_lms
from openedx.core.lib.token_utils import JwtBuilder from openedx.core.lib.token_utils import JwtBuilder
from student.tests.factories import UserFactory, AdminFactory from student.tests.factories import UserFactory, AdminFactory
from util.date_utils import to_timestamp from util.date_utils import to_timestamp
...@@ -113,7 +113,7 @@ class ReadOnlyMixin(object): ...@@ -113,7 +113,7 @@ class ReadOnlyMixin(object):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CreditCourseViewSetTests(AuthMixin, UserMixin, TestCase): class CreditCourseViewSetTests(AuthMixin, UserMixin, TestCase):
""" Tests for the CreditCourse endpoints. """ Tests for the CreditCourse endpoints.
...@@ -276,7 +276,7 @@ class CreditCourseViewSetTests(AuthMixin, UserMixin, TestCase): ...@@ -276,7 +276,7 @@ class CreditCourseViewSetTests(AuthMixin, UserMixin, TestCase):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CreditProviderViewSetTests(ApiTestCaseMixin, ReadOnlyMixin, AuthMixin, UserMixin, TestCase): class CreditProviderViewSetTests(ApiTestCaseMixin, ReadOnlyMixin, AuthMixin, UserMixin, TestCase):
""" Tests for CreditProviderViewSet. """ """ Tests for CreditProviderViewSet. """
list_path = 'credit:creditprovider-list' list_path = 'credit:creditprovider-list'
...@@ -320,7 +320,7 @@ class CreditProviderViewSetTests(ApiTestCaseMixin, ReadOnlyMixin, AuthMixin, Use ...@@ -320,7 +320,7 @@ class CreditProviderViewSetTests(ApiTestCaseMixin, ReadOnlyMixin, AuthMixin, Use
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CreditProviderRequestCreateViewTests(ApiTestCaseMixin, UserMixin, TestCase): class CreditProviderRequestCreateViewTests(ApiTestCaseMixin, UserMixin, TestCase):
""" Tests for CreditProviderRequestCreateView. """ """ Tests for CreditProviderRequestCreateView. """
...@@ -470,7 +470,7 @@ class CreditProviderRequestCreateViewTests(ApiTestCaseMixin, UserMixin, TestCase ...@@ -470,7 +470,7 @@ class CreditProviderRequestCreateViewTests(ApiTestCaseMixin, UserMixin, TestCase
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CreditProviderCallbackViewTests(UserMixin, TestCase): class CreditProviderCallbackViewTests(UserMixin, TestCase):
""" Tests for CreditProviderCallbackView. """ """ Tests for CreditProviderCallbackView. """
...@@ -624,7 +624,7 @@ class CreditProviderCallbackViewTests(UserMixin, TestCase): ...@@ -624,7 +624,7 @@ class CreditProviderCallbackViewTests(UserMixin, TestCase):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class CreditEligibilityViewTests(AuthMixin, UserMixin, ReadOnlyMixin, TestCase): class CreditEligibilityViewTests(AuthMixin, UserMixin, ReadOnlyMixin, TestCase):
""" Tests for CreditEligibilityView. """ """ Tests for CreditEligibilityView. """
view_name = 'credit:eligibility_details' view_name = 'credit:eligibility_details'
......
...@@ -5,7 +5,6 @@ Tests for EmbargoMiddleware ...@@ -5,7 +5,6 @@ Tests for EmbargoMiddleware
from contextlib import contextmanager from contextlib import contextmanager
import mock import mock
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
import unittest
import pygeoip import pygeoip
import ddt import ddt
...@@ -14,6 +13,7 @@ from django.test.utils import override_settings ...@@ -14,6 +13,7 @@ from django.test.utils import override_settings
from django.core.cache import cache from django.core.cache import cache
from django.db import connection from django.db import connection
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ( from xmodule.modulestore.tests.django_utils import (
...@@ -41,7 +41,7 @@ MODULESTORE_CONFIG = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {}) ...@@ -41,7 +41,7 @@ MODULESTORE_CONFIG = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {})
@attr(shard=3) @attr(shard=3)
@ddt.ddt @ddt.ddt
@override_settings(MODULESTORE=MODULESTORE_CONFIG) @override_settings(MODULESTORE=MODULESTORE_CONFIG)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@mock.patch.dict(settings.FEATURES, {'EMBARGO': True}) @mock.patch.dict(settings.FEATURES, {'EMBARGO': True})
class EmbargoCheckAccessApiTests(ModuleStoreTestCase): class EmbargoCheckAccessApiTests(ModuleStoreTestCase):
"""Test the embargo API calls to determine whether a user has access. """ """Test the embargo API calls to determine whether a user has access. """
...@@ -239,7 +239,7 @@ class EmbargoCheckAccessApiTests(ModuleStoreTestCase): ...@@ -239,7 +239,7 @@ class EmbargoCheckAccessApiTests(ModuleStoreTestCase):
@ddt.ddt @ddt.ddt
@override_settings(MODULESTORE=MODULESTORE_CONFIG) @override_settings(MODULESTORE=MODULESTORE_CONFIG)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class EmbargoMessageUrlApiTests(UrlResetMixin, ModuleStoreTestCase): class EmbargoMessageUrlApiTests(UrlResetMixin, ModuleStoreTestCase):
"""Test the embargo API calls for retrieving the blocking message URLs. """ """Test the embargo API calls for retrieving the blocking message URLs. """
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
Tests for EmbargoMiddleware with CountryAccessRules Tests for EmbargoMiddleware with CountryAccessRules
""" """
import unittest
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
import ddt import ddt
...@@ -11,11 +10,12 @@ from django.core.urlresolvers import reverse ...@@ -11,11 +10,12 @@ from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from django.core.cache import cache as django_cache from django.core.cache import cache as django_cache
from config_models.models import cache as config_cache
from openedx.core.djangolib.testing.utils import skip_unless_lms
from util.testing import UrlResetMixin from util.testing import UrlResetMixin
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from config_models.models import cache as config_cache
from ..models import RestrictedCourse, IPFilter from ..models import RestrictedCourse, IPFilter
from ..test_utils import restrict_course from ..test_utils import restrict_course
...@@ -23,7 +23,7 @@ from ..test_utils import restrict_course ...@@ -23,7 +23,7 @@ from ..test_utils import restrict_course
@attr(shard=3) @attr(shard=3)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class EmbargoMiddlewareAccessTests(UrlResetMixin, ModuleStoreTestCase): class EmbargoMiddlewareAccessTests(UrlResetMixin, ModuleStoreTestCase):
"""Tests of embargo middleware country access rules. """Tests of embargo middleware country access rules.
......
"""Tests for embargo app views. """ """Tests for embargo app views. """
import unittest
from mock import patch from mock import patch
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
...@@ -8,11 +7,11 @@ import ddt ...@@ -8,11 +7,11 @@ import ddt
from util.testing import UrlResetMixin from util.testing import UrlResetMixin
from .. import messages from .. import messages
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@ddt.ddt @ddt.ddt
class CourseAccessMessageViewTest(CacheIsolationTestCase, UrlResetMixin): class CourseAccessMessageViewTest(CacheIsolationTestCase, UrlResetMixin):
"""Tests for the courseware access message view. """Tests for the courseware access message view.
......
...@@ -3,10 +3,10 @@ Provides unit tests for SSL based authentication portions ...@@ -3,10 +3,10 @@ Provides unit tests for SSL based authentication portions
of the external_auth app. of the external_auth app.
""" """
# pylint: disable=no-member # pylint: disable=no-member
from contextlib import contextmanager
import copy import copy
import unittest from mock import Mock, patch
from contextlib import contextmanager
from django.conf import settings from django.conf import settings
from django.contrib.auth import SESSION_KEY from django.contrib.auth import SESSION_KEY
from django.contrib.auth.models import AnonymousUser, User from django.contrib.auth.models import AnonymousUser, User
...@@ -15,10 +15,10 @@ from django.core.urlresolvers import reverse ...@@ -15,10 +15,10 @@ from django.core.urlresolvers import reverse
from django.test.client import Client from django.test.client import Client
from django.test.client import RequestFactory from django.test.client import RequestFactory
from django.test.utils import override_settings from django.test.utils import override_settings
from mock import Mock, patch
from openedx.core.djangoapps.external_auth.models import ExternalAuthMap from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
import openedx.core.djangoapps.external_auth.views as external_auth_views import openedx.core.djangoapps.external_auth.views as external_auth_views
from openedx.core.djangolib.testing.utils import skip_unless_cms, skip_unless_lms
from student.models import CourseEnrollment from student.models import CourseEnrollment
from student.roles import CourseStaffRole from student.roles import CourseStaffRole
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
...@@ -81,7 +81,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -81,7 +81,7 @@ class SSLClientTest(ModuleStoreTestCase):
self.factory = RequestFactory() self.factory = RequestFactory()
self.mock = Mock() self.mock = Mock()
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
def test_ssl_login_with_signup_lms(self): def test_ssl_login_with_signup_lms(self):
""" """
Validate that an SSL login creates an eamap user and Validate that an SSL login creates an eamap user and
...@@ -101,7 +101,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -101,7 +101,7 @@ class SSLClientTest(ModuleStoreTestCase):
with self.assertRaises(User.DoesNotExist): with self.assertRaises(User.DoesNotExist):
User.objects.get(email=self.USER_EMAIL) User.objects.get(email=self.USER_EMAIL)
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
def test_ssl_login_with_signup_cms(self): def test_ssl_login_with_signup_cms(self):
""" """
Validate that an SSL login creates an eamap user and Validate that an SSL login creates an eamap user and
...@@ -120,7 +120,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -120,7 +120,7 @@ class SSLClientTest(ModuleStoreTestCase):
with self.assertRaises(User.DoesNotExist): with self.assertRaises(User.DoesNotExist):
User.objects.get(email=self.USER_EMAIL) User.objects.get(email=self.USER_EMAIL)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_ssl_login_without_signup_lms(self): def test_ssl_login_without_signup_lms(self):
""" """
...@@ -140,7 +140,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -140,7 +140,7 @@ class SSLClientTest(ModuleStoreTestCase):
except ExternalAuthMap.DoesNotExist, ex: except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex))) self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex)))
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_ssl_login_without_signup_cms(self): def test_ssl_login_without_signup_cms(self):
""" """
...@@ -166,7 +166,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -166,7 +166,7 @@ class SSLClientTest(ModuleStoreTestCase):
except ExternalAuthMap.DoesNotExist, ex: except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex))) self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex)))
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_default_login_decorator_ssl(self): def test_default_login_decorator_ssl(self):
""" """
...@@ -184,7 +184,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -184,7 +184,7 @@ class SSLClientTest(ModuleStoreTestCase):
response.redirect_chain[-1]) response.redirect_chain[-1])
self.assertIn(SESSION_KEY, self.client.session) self.assertIn(SESSION_KEY, self.client.session)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_registration_page_bypass(self): def test_registration_page_bypass(self):
""" """
...@@ -198,7 +198,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -198,7 +198,7 @@ class SSLClientTest(ModuleStoreTestCase):
response.redirect_chain[-1]) response.redirect_chain[-1])
self.assertIn(SESSION_KEY, self.client.session) self.assertIn(SESSION_KEY, self.client.session)
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_cms_registration_page_bypass(self): def test_cms_registration_page_bypass(self):
""" """
...@@ -217,7 +217,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -217,7 +217,7 @@ class SSLClientTest(ModuleStoreTestCase):
response = self.client.get(reverse('signup'), follow=True) response = self.client.get(reverse('signup'), follow=True)
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_signin_page_bypass(self): def test_signin_page_bypass(self):
""" """
...@@ -238,7 +238,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -238,7 +238,7 @@ class SSLClientTest(ModuleStoreTestCase):
response.redirect_chain[-1]) response.redirect_chain[-1])
self.assertIn(SESSION_KEY, self.client.session) self.assertIn(SESSION_KEY, self.client.session)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_ssl_bad_eamap(self): def test_ssl_bad_eamap(self):
""" """
...@@ -263,7 +263,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -263,7 +263,7 @@ class SSLClientTest(ModuleStoreTestCase):
SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)) SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL))
self.assertIn(SESSION_KEY, self.client.session) self.assertIn(SESSION_KEY, self.client.session)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITHOUT_SSL_AUTH) @override_settings(FEATURES=FEATURES_WITHOUT_SSL_AUTH)
def test_ssl_decorator_no_certs(self): def test_ssl_decorator_no_certs(self):
"""Make sure no external auth happens without SSL enabled""" """Make sure no external auth happens without SSL enabled"""
...@@ -279,7 +279,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -279,7 +279,7 @@ class SSLClientTest(ModuleStoreTestCase):
self.assertTrue(self.mock.called) self.assertTrue(self.mock.called)
self.assertEqual(0, len(ExternalAuthMap.objects.all())) self.assertEqual(0, len(ExternalAuthMap.objects.all()))
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
def test_ssl_login_decorator(self): def test_ssl_login_decorator(self):
"""Create mock function to test ssl login decorator""" """Create mock function to test ssl login decorator"""
...@@ -305,7 +305,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -305,7 +305,7 @@ class SSLClientTest(ModuleStoreTestCase):
dec_mock(request) dec_mock(request)
self.assertTrue(self.mock.called) self.assertTrue(self.mock.called)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_ssl_decorator_auto_signup(self): def test_ssl_decorator_auto_signup(self):
""" """
...@@ -330,7 +330,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -330,7 +330,7 @@ class SSLClientTest(ModuleStoreTestCase):
self.assertTrue(self.mock.called) self.assertTrue(self.mock.called)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_AUTO_ACTIVATE) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_AUTO_ACTIVATE)
def test_ssl_lms_redirection(self): def test_ssl_lms_redirection(self):
""" """
...@@ -361,7 +361,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -361,7 +361,7 @@ class SSLClientTest(ModuleStoreTestCase):
response.redirect_chain[-1]) response.redirect_chain[-1])
self.assertIn(SESSION_KEY, self.client.session) self.assertIn(SESSION_KEY, self.client.session)
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_AUTO_ACTIVATE) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_AUTO_ACTIVATE)
def test_ssl_cms_redirection(self): def test_ssl_cms_redirection(self):
""" """
...@@ -393,7 +393,7 @@ class SSLClientTest(ModuleStoreTestCase): ...@@ -393,7 +393,7 @@ class SSLClientTest(ModuleStoreTestCase):
response.redirect_chain[-1]) response.redirect_chain[-1])
self.assertIn(SESSION_KEY, self.client.session) self.assertIn(SESSION_KEY, self.client.session)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_AUTO_ACTIVATE) @override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_AUTO_ACTIVATE)
def test_ssl_logout(self): def test_ssl_logout(self):
""" """
......
...@@ -5,9 +5,7 @@ from contextlib import closing ...@@ -5,9 +5,7 @@ from contextlib import closing
from itertools import product from itertools import product
import os import os
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
import unittest
from django.conf import settings
from django.core.files.uploadedfile import UploadedFile from django.core.files.uploadedfile import UploadedFile
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
...@@ -17,6 +15,7 @@ from nose.plugins.attrib import attr ...@@ -17,6 +15,7 @@ from nose.plugins.attrib import attr
import piexif import piexif
from PIL import Image from PIL import Image
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ..exceptions import ImageValidationError from ..exceptions import ImageValidationError
from ..images import ( from ..images import (
create_profile_images, create_profile_images,
...@@ -31,7 +30,7 @@ from .helpers import make_image_file, make_uploaded_file ...@@ -31,7 +30,7 @@ from .helpers import make_image_file, make_uploaded_file
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
class TestValidateUploadedImage(TestCase): class TestValidateUploadedImage(TestCase):
""" """
Test validate_uploaded_image Test validate_uploaded_image
...@@ -127,7 +126,7 @@ class TestValidateUploadedImage(TestCase): ...@@ -127,7 +126,7 @@ class TestValidateUploadedImage(TestCase):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
class TestGenerateProfileImages(TestCase): class TestGenerateProfileImages(TestCase):
""" """
Test create_profile_images Test create_profile_images
...@@ -224,7 +223,7 @@ class TestGenerateProfileImages(TestCase): ...@@ -224,7 +223,7 @@ class TestGenerateProfileImages(TestCase):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
class TestRemoveProfileImages(TestCase): class TestRemoveProfileImages(TestCase):
""" """
Test remove_profile_images Test remove_profile_images
......
...@@ -5,9 +5,7 @@ from contextlib import closing ...@@ -5,9 +5,7 @@ from contextlib import closing
import datetime import datetime
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from pytz import UTC from pytz import UTC
import unittest
from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponse from django.http import HttpResponse
...@@ -24,6 +22,7 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import ( ...@@ -24,6 +22,7 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import (
get_profile_image_names, get_profile_image_names,
get_profile_image_storage, get_profile_image_storage,
) )
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ..images import create_profile_images, ImageValidationError from ..images import create_profile_images, ImageValidationError
from ..views import LOG_MESSAGE_CREATE, LOG_MESSAGE_DELETE from ..views import LOG_MESSAGE_CREATE, LOG_MESSAGE_DELETE
...@@ -153,7 +152,7 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin): ...@@ -153,7 +152,7 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
@mock.patch('openedx.core.djangoapps.profile_images.views.log') @mock.patch('openedx.core.djangoapps.profile_images.views.log')
class ProfileImageViewGeneralTestCase(ProfileImageEndpointMixin, APITestCase): class ProfileImageViewGeneralTestCase(ProfileImageEndpointMixin, APITestCase):
""" """
...@@ -174,7 +173,7 @@ class ProfileImageViewGeneralTestCase(ProfileImageEndpointMixin, APITestCase): ...@@ -174,7 +173,7 @@ class ProfileImageViewGeneralTestCase(ProfileImageEndpointMixin, APITestCase):
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
@mock.patch('openedx.core.djangoapps.profile_images.views.log') @mock.patch('openedx.core.djangoapps.profile_images.views.log')
class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase): class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
""" """
...@@ -384,7 +383,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase): ...@@ -384,7 +383,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
@mock.patch('openedx.core.djangoapps.profile_images.views.log') @mock.patch('openedx.core.djangoapps.profile_images.views.log')
class ProfileImageViewDeleteTestCase(ProfileImageEndpointMixin, APITestCase): class ProfileImageViewDeleteTestCase(ProfileImageEndpointMixin, APITestCase):
""" """
...@@ -515,7 +514,7 @@ class DeprecatedProfileImageTestMixin(ProfileImageEndpointMixin): ...@@ -515,7 +514,7 @@ class DeprecatedProfileImageTestMixin(ProfileImageEndpointMixin):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
@mock.patch('openedx.core.djangoapps.profile_images.views.log') @mock.patch('openedx.core.djangoapps.profile_images.views.log')
class DeprecatedProfileImageUploadTestCase(DeprecatedProfileImageTestMixin, APITestCase): class DeprecatedProfileImageUploadTestCase(DeprecatedProfileImageTestMixin, APITestCase):
""" """
...@@ -528,7 +527,7 @@ class DeprecatedProfileImageUploadTestCase(DeprecatedProfileImageTestMixin, APIT ...@@ -528,7 +527,7 @@ class DeprecatedProfileImageUploadTestCase(DeprecatedProfileImageTestMixin, APIT
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Profile Image API is only supported in LMS') @skip_unless_lms
@mock.patch('openedx.core.djangoapps.profile_images.views.log') @mock.patch('openedx.core.djangoapps.profile_images.views.log')
class DeprecatedProfileImageRemoveTestCase(DeprecatedProfileImageTestMixin, APITestCase): class DeprecatedProfileImageRemoveTestCase(DeprecatedProfileImageTestMixin, APITestCase):
""" """
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
Tests for programs celery tasks. Tests for programs celery tasks.
""" """
import json import json
import unittest
from celery.exceptions import MaxRetriesExceededError from celery.exceptions import MaxRetriesExceededError
import ddt import ddt
...@@ -20,7 +19,7 @@ from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfi ...@@ -20,7 +19,7 @@ from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfi
from openedx.core.djangoapps.programs.tests import factories from openedx.core.djangoapps.programs.tests import factories
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
from openedx.core.djangoapps.programs.tasks.v1 import tasks from openedx.core.djangoapps.programs.tasks.v1 import tasks
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
...@@ -28,7 +27,7 @@ TASKS_MODULE = 'openedx.core.djangoapps.programs.tasks.v1.tasks' ...@@ -28,7 +27,7 @@ TASKS_MODULE = 'openedx.core.djangoapps.programs.tasks.v1.tasks'
UTILS_MODULE = 'openedx.core.djangoapps.programs.utils' UTILS_MODULE = 'openedx.core.djangoapps.programs.utils'
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class GetApiClientTestCase(TestCase, ProgramsApiConfigMixin): class GetApiClientTestCase(TestCase, ProgramsApiConfigMixin):
""" """
Test the get_api_client function Test the get_api_client function
...@@ -53,7 +52,7 @@ class GetApiClientTestCase(TestCase, ProgramsApiConfigMixin): ...@@ -53,7 +52,7 @@ class GetApiClientTestCase(TestCase, ProgramsApiConfigMixin):
@httpretty.activate @httpretty.activate
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class GetCompletedProgramsTestCase(ProgramsApiConfigMixin, CacheIsolationTestCase): class GetCompletedProgramsTestCase(ProgramsApiConfigMixin, CacheIsolationTestCase):
""" """
Test the get_completed_programs function Test the get_completed_programs function
...@@ -113,7 +112,7 @@ class GetCompletedProgramsTestCase(ProgramsApiConfigMixin, CacheIsolationTestCas ...@@ -113,7 +112,7 @@ class GetCompletedProgramsTestCase(ProgramsApiConfigMixin, CacheIsolationTestCas
self._assert_num_requests(1) self._assert_num_requests(1)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class GetAwardedCertificateProgramsTestCase(TestCase): class GetAwardedCertificateProgramsTestCase(TestCase):
""" """
Test the get_awarded_certificate_programs function Test the get_awarded_certificate_programs function
...@@ -154,7 +153,7 @@ class GetAwardedCertificateProgramsTestCase(TestCase): ...@@ -154,7 +153,7 @@ class GetAwardedCertificateProgramsTestCase(TestCase):
self.assertEqual(result, [1]) self.assertEqual(result, [1])
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class AwardProgramCertificateTestCase(TestCase): class AwardProgramCertificateTestCase(TestCase):
""" """
Test the award_program_certificate function Test the award_program_certificate function
...@@ -183,7 +182,7 @@ class AwardProgramCertificateTestCase(TestCase): ...@@ -183,7 +182,7 @@ class AwardProgramCertificateTestCase(TestCase):
self.assertEqual(json.loads(httpretty.last_request().body), expected_body) self.assertEqual(json.loads(httpretty.last_request().body), expected_body)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@ddt.ddt @ddt.ddt
@mock.patch(TASKS_MODULE + '.award_program_certificate') @mock.patch(TASKS_MODULE + '.award_program_certificate')
@mock.patch(TASKS_MODULE + '.get_awarded_certificate_programs') @mock.patch(TASKS_MODULE + '.get_awarded_certificate_programs')
......
"""Tests for the backpopulate_program_credentials management command.""" """Tests for the backpopulate_program_credentials management command."""
import json import json
from unittest import skipUnless
import ddt import ddt
from django.conf import settings
from django.core.management import call_command, CommandError from django.core.management import call_command, CommandError
from django.test import TestCase from django.test import TestCase
from edx_oauth2_provider.tests.factories import ClientFactory from edx_oauth2_provider.tests.factories import ClientFactory
...@@ -17,6 +15,7 @@ from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFact ...@@ -17,6 +15,7 @@ from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFact
from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.tests import factories from openedx.core.djangoapps.programs.tests import factories
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
...@@ -26,7 +25,7 @@ COMMAND_MODULE = 'openedx.core.djangoapps.programs.management.commands.backpopul ...@@ -26,7 +25,7 @@ COMMAND_MODULE = 'openedx.core.djangoapps.programs.management.commands.backpopul
@ddt.ddt @ddt.ddt
@httpretty.activate @httpretty.activate
@mock.patch(COMMAND_MODULE + '.award_program_certificates.delay') @mock.patch(COMMAND_MODULE + '.award_program_certificates.delay')
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase): class BackpopulateProgramCredentialsTests(ProgramsApiConfigMixin, TestCase):
"""Tests for the backpopulate_program_credentials management command.""" """Tests for the backpopulate_program_credentials management command."""
course_id, alternate_course_id = 'org/course/run', 'org/alternate/run' course_id, alternate_course_id = 'org/course/run', 'org/alternate/run'
......
...@@ -2,11 +2,9 @@ ...@@ -2,11 +2,9 @@
import copy import copy
import datetime import datetime
import json import json
from unittest import skipUnless
import uuid import uuid
import ddt import ddt
from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
...@@ -29,7 +27,7 @@ from openedx.core.djangoapps.programs import utils ...@@ -29,7 +27,7 @@ from openedx.core.djangoapps.programs import utils
from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.tests import factories from openedx.core.djangoapps.programs.tests import factories
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin, ProgramsDataMixin
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory
from util.date_utils import strftime_localized from util.date_utils import strftime_localized
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
...@@ -45,7 +43,7 @@ MARKETING_URL = 'https://www.example.com/marketing/path' ...@@ -45,7 +43,7 @@ MARKETING_URL = 'https://www.example.com/marketing/path'
@ddt.ddt @ddt.ddt
@attr(shard=2) @attr(shard=2)
@httpretty.activate @httpretty.activate
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, CredentialsDataMixin, class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, CredentialsDataMixin,
CredentialsApiConfigMixin, CacheIsolationTestCase): CredentialsApiConfigMixin, CacheIsolationTestCase):
"""Tests covering the retrieval of programs from the Programs service.""" """Tests covering the retrieval of programs from the Programs service."""
...@@ -190,7 +188,7 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -190,7 +188,7 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
self.assertEqual(actual, []) self.assertEqual(actual, [])
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class GetProgramsByRunTests(TestCase): class GetProgramsByRunTests(TestCase):
"""Tests verifying that programs are inverted correctly.""" """Tests verifying that programs are inverted correctly."""
maxDiff = None maxDiff = None
...@@ -262,7 +260,7 @@ class GetProgramsByRunTests(TestCase): ...@@ -262,7 +260,7 @@ class GetProgramsByRunTests(TestCase):
self.assertEqual(course_ids, []) self.assertEqual(course_ids, [])
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class GetCompletedCoursesTestCase(TestCase): class GetCompletedCoursesTestCase(TestCase):
""" """
Test the get_completed_courses function Test the get_completed_courses function
...@@ -308,7 +306,7 @@ class GetCompletedCoursesTestCase(TestCase): ...@@ -308,7 +306,7 @@ class GetCompletedCoursesTestCase(TestCase):
@attr(shard=2) @attr(shard=2)
@httpretty.activate @httpretty.activate
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestProgramProgressMeter(ProgramsApiConfigMixin, TestCase): class TestProgramProgressMeter(ProgramsApiConfigMixin, TestCase):
"""Tests of the program progress utility class.""" """Tests of the program progress utility class."""
def setUp(self): def setUp(self):
...@@ -700,7 +698,7 @@ class TestProgramProgressMeter(ProgramsApiConfigMixin, TestCase): ...@@ -700,7 +698,7 @@ class TestProgramProgressMeter(ProgramsApiConfigMixin, TestCase):
@ddt.ddt @ddt.ddt
@override_settings(ECOMMERCE_PUBLIC_URL_ROOT=ECOMMERCE_URL_ROOT) @override_settings(ECOMMERCE_PUBLIC_URL_ROOT=ECOMMERCE_URL_ROOT)
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@mock.patch(UTILS_MODULE + '.get_run_marketing_url', mock.Mock(return_value=MARKETING_URL)) @mock.patch(UTILS_MODULE + '.get_run_marketing_url', mock.Mock(return_value=MARKETING_URL))
class TestProgramDataExtender(ProgramsApiConfigMixin, ModuleStoreTestCase): class TestProgramDataExtender(ProgramsApiConfigMixin, ModuleStoreTestCase):
"""Tests of the program data extender utility class.""" """Tests of the program data extender utility class."""
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
Test site_configuration middleware. Test site_configuration middleware.
""" """
import ddt import ddt
import unittest
from mock import patch from mock import patch
from django.conf import settings from django.conf import settings
...@@ -22,6 +21,7 @@ from microsite_configuration.tests.tests import ( ...@@ -22,6 +21,7 @@ from microsite_configuration.tests.tests import (
MICROSITE_BACKENDS, MICROSITE_BACKENDS,
) )
from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory, SiteFactory from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory, SiteFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
# NOTE: We set SESSION_SAVE_EVERY_REQUEST to True in order to make sure # NOTE: We set SESSION_SAVE_EVERY_REQUEST to True in order to make sure
...@@ -29,7 +29,7 @@ from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfi ...@@ -29,7 +29,7 @@ from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfi
# pylint: disable=no-member, protected-access # pylint: disable=no-member, protected-access
@ddt.ddt @ddt.ddt
@override_settings(SESSION_SAVE_EVERY_REQUEST=True) @override_settings(SESSION_SAVE_EVERY_REQUEST=True)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class SessionCookieDomainMicrositeOverrideTests(DatabaseMicrositeTestCase): class SessionCookieDomainMicrositeOverrideTests(DatabaseMicrositeTestCase):
""" """
Tests regarding the session cookie management in the middlware for Microsites Tests regarding the session cookie management in the middlware for Microsites
......
""" """
Tests for comprehensive theme static files finders. Tests for comprehensive theme static files finders.
""" """
import unittest
from django.conf import settings from django.conf import settings
from django.test import TestCase from django.test import TestCase
from openedx.core.djangoapps.theming.finders import ThemeFilesFinder from openedx.core.djangoapps.theming.finders import ThemeFilesFinder
from openedx.core.djangolib.testing.utils import skip_unless_lms
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestThemeFinders(TestCase): class TestThemeFinders(TestCase):
""" """
Test comprehensive theming static files finders. Test comprehensive theming static files finders.
......
""" """
Test helpers for Comprehensive Theming. Test helpers for Comprehensive Theming.
""" """
import unittest
from mock import patch, Mock from mock import patch, Mock
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
...@@ -12,6 +11,7 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_ ...@@ -12,6 +11,7 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_
from openedx.core.djangoapps.theming import helpers as theming_helpers from openedx.core.djangoapps.theming import helpers as theming_helpers
from openedx.core.djangoapps.theming.helpers import get_template_path_with_theme, strip_site_theme_templates_path, \ from openedx.core.djangoapps.theming.helpers import get_template_path_with_theme, strip_site_theme_templates_path, \
get_themes, Theme, get_theme_base_dir get_themes, Theme, get_theme_base_dir
from openedx.core.djangolib.testing.utils import skip_unless_cms, skip_unless_lms
class TestHelpers(TestCase): class TestHelpers(TestCase):
...@@ -201,7 +201,7 @@ class TestHelpers(TestCase): ...@@ -201,7 +201,7 @@ class TestHelpers(TestCase):
self.assertEqual(theming_helpers.get_template_path("about.html"), "/microsite/about.html") self.assertEqual(theming_helpers.get_template_path("about.html"), "/microsite/about.html")
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestHelpersLMS(TestCase): class TestHelpersLMS(TestCase):
"""Test comprehensive theming helper functions.""" """Test comprehensive theming helper functions."""
...@@ -244,7 +244,7 @@ class TestHelpersLMS(TestCase): ...@@ -244,7 +244,7 @@ class TestHelpersLMS(TestCase):
self.assertEqual(template_path, '/red-theme/lms/templates/header.html') self.assertEqual(template_path, '/red-theme/lms/templates/header.html')
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
class TestHelpersCMS(TestCase): class TestHelpersCMS(TestCase):
"""Test comprehensive theming helper functions.""" """Test comprehensive theming helper functions."""
......
""" """
Tests for microsites and comprehensive themes. Tests for microsites and comprehensive themes.
""" """
import unittest
from django.conf import settings from django.conf import settings
from django.test import TestCase from django.test import TestCase
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from openedx.core.djangoapps.theming.models import SiteTheme from openedx.core.djangoapps.theming.models import SiteTheme
from openedx.core.djangolib.testing.utils import skip_unless_lms
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestComprehensiveThemeLMS(TestCase): class TestComprehensiveThemeLMS(TestCase):
""" """
Test html, sass and static file overrides for comprehensive themes. Test html, sass and static file overrides for comprehensive themes.
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
Tests for comprehensive theme static files storage classes. Tests for comprehensive theme static files storage classes.
""" """
import ddt import ddt
import unittest
import re import re
from mock import patch from mock import patch
...@@ -12,9 +11,10 @@ from django.conf import settings ...@@ -12,9 +11,10 @@ from django.conf import settings
from openedx.core.djangoapps.theming.helpers import get_theme_base_dirs, Theme, get_theme_base_dir from openedx.core.djangoapps.theming.helpers import get_theme_base_dirs, Theme, get_theme_base_dir
from openedx.core.djangoapps.theming.storage import ThemeStorage from openedx.core.djangoapps.theming.storage import ThemeStorage
from openedx.core.djangolib.testing.utils import skip_unless_lms
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
@ddt.ddt @ddt.ddt
class TestStorageLMS(TestCase): class TestStorageLMS(TestCase):
""" """
......
""" """
Tests for Themeing locales Tests for Theming locales
""" """
import os
import unittest
from django.conf import settings from django.conf import settings
from django.test import TestCase from django.test import TestCase
import os
from openedx.core.djangolib.testing.utils import skip_unless_lms
class TestComprehensiveThemeLocale(TestCase): class TestComprehensiveThemeLocale(TestCase):
""" """
Test Comprehensive Theme Locales Test Comprehensive Theme Locales
""" """
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
def test_theme_locale_path_in_settings(self): def test_theme_locale_path_in_settings(self):
""" """
test comprehensive theming paths in settings. test comprehensive theming paths in settings.
......
""" """
Tests for comprehensive themes. Tests for comprehensive themes.
""" """
import unittest
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
from django.contrib import staticfiles from django.contrib import staticfiles
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
from openedx.core.djangolib.testing.utils import skip_unless_cms, skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestComprehensiveThemeLMS(TestCase): class TestComprehensiveThemeLMS(TestCase):
""" """
Test html, sass and static file overrides for comprehensive themes. Test html, sass and static file overrides for comprehensive themes.
...@@ -66,7 +65,7 @@ class TestComprehensiveThemeLMS(TestCase): ...@@ -66,7 +65,7 @@ class TestComprehensiveThemeLMS(TestCase):
self.assertEqual(result, settings.TEST_THEME / 'lms/static/images/logo.png') self.assertEqual(result, settings.TEST_THEME / 'lms/static/images/logo.png')
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
class TestComprehensiveThemeCMS(TestCase): class TestComprehensiveThemeCMS(TestCase):
""" """
Test html, sass and static file overrides for comprehensive themes. Test html, sass and static file overrides for comprehensive themes.
...@@ -92,7 +91,7 @@ class TestComprehensiveThemeCMS(TestCase): ...@@ -92,7 +91,7 @@ class TestComprehensiveThemeCMS(TestCase):
self.assertContains(resp, "Login Page override for test-theme.") self.assertContains(resp, "Login Page override for test-theme.")
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestComprehensiveThemeDisabledLMS(TestCase): class TestComprehensiveThemeDisabledLMS(TestCase):
""" """
Test Sass compilation order and sass overrides for comprehensive themes. Test Sass compilation order and sass overrides for comprehensive themes.
...@@ -115,7 +114,7 @@ class TestComprehensiveThemeDisabledLMS(TestCase): ...@@ -115,7 +114,7 @@ class TestComprehensiveThemeDisabledLMS(TestCase):
self.assertEqual(result, settings.REPO_ROOT / 'lms/static/images/logo.png') self.assertEqual(result, settings.REPO_ROOT / 'lms/static/images/logo.png')
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms') @skip_unless_cms
class TestComprehensiveThemeDisabledCMS(TestCase): class TestComprehensiveThemeDisabledCMS(TestCase):
""" """
Test default html, sass and static file when no theme is applied. Test default html, sass and static file when no theme is applied.
...@@ -139,7 +138,7 @@ class TestComprehensiveThemeDisabledCMS(TestCase): ...@@ -139,7 +138,7 @@ class TestComprehensiveThemeDisabledCMS(TestCase):
self.assertNotContains(resp, "Login Page override for test-theme.") self.assertNotContains(resp, "Login Page override for test-theme.")
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestStanfordTheme(TestCase): class TestStanfordTheme(TestCase):
""" """
Test html, sass and static file overrides for stanford theme. Test html, sass and static file overrides for stanford theme.
......
...@@ -17,6 +17,7 @@ from django.conf import settings ...@@ -17,6 +17,7 @@ from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core import mail from django.core import mail
from django.test.client import RequestFactory from django.test.client import RequestFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.models import PendingEmailChange from student.models import PendingEmailChange
from student.tests.tests import UserSettingsEventTestMixin from student.tests.tests import UserSettingsEventTestMixin
from ...errors import ( from ...errors import (
...@@ -35,7 +36,7 @@ def mock_render_to_string(template_name, context): ...@@ -35,7 +36,7 @@ def mock_render_to_string(template_name, context):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS') @skip_unless_lms
class TestAccountApi(UserSettingsEventTestMixin, TestCase): class TestAccountApi(UserSettingsEventTestMixin, TestCase):
""" """
These tests specifically cover the parts of the API methods that are not covered by test_views.py. These tests specifically cover the parts of the API methods that are not covered by test_views.py.
...@@ -239,7 +240,7 @@ class TestAccountApi(UserSettingsEventTestMixin, TestCase): ...@@ -239,7 +240,7 @@ class TestAccountApi(UserSettingsEventTestMixin, TestCase):
{'full': 50, 'small': 10}, {'full': 50, 'small': 10},
clear=True clear=True
) )
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS') @skip_unless_lms
class AccountSettingsOnCreationTest(TestCase): class AccountSettingsOnCreationTest(TestCase):
# pylint: disable=missing-docstring # pylint: disable=missing-docstring
...@@ -333,7 +334,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase): ...@@ -333,7 +334,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase):
u'a' * (PASSWORD_MAX_LENGTH + 1) u'a' * (PASSWORD_MAX_LENGTH + 1)
] ]
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
def test_activate_account(self): def test_activate_account(self):
# Create the account, which is initially inactive # Create the account, which is initially inactive
activation_key = create_account(self.USERNAME, self.PASSWORD, self.EMAIL) activation_key = create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
...@@ -393,7 +394,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase): ...@@ -393,7 +394,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase):
def test_activate_account_invalid_key(self): def test_activate_account_invalid_key(self):
activate_account(u'invalid') activate_account(u'invalid')
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
def test_request_password_change(self): def test_request_password_change(self):
# Create and activate an account # Create and activate an account
activation_key = create_account(self.USERNAME, self.PASSWORD, self.EMAIL) activation_key = create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
...@@ -411,7 +412,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase): ...@@ -411,7 +412,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase):
result = re.search(r'(?P<url>https?://[^\s]+)', email_body) result = re.search(r'(?P<url>https?://[^\s]+)', email_body)
self.assertIsNot(result, None) self.assertIsNot(result, None)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
def test_request_password_change_invalid_user(self): def test_request_password_change_invalid_user(self):
with self.assertRaises(UserNotFound): with self.assertRaises(UserNotFound):
request_password_change(self.EMAIL, self.ORIG_HOST, self.IS_SECURE) request_password_change(self.EMAIL, self.ORIG_HOST, self.IS_SECURE)
...@@ -419,7 +420,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase): ...@@ -419,7 +420,7 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase):
# Verify that no email messages have been sent # Verify that no email messages have been sent
self.assertEqual(len(mail.outbox), 0) self.assertEqual(len(mail.outbox), 0)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') @skip_unless_lms
def test_request_password_change_inactive_user(self): def test_request_password_change_inactive_user(self):
# Create an account, but do not activate it # Create an account, but do not activate it
create_account(self.USERNAME, self.PASSWORD, self.EMAIL) create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
......
...@@ -6,13 +6,12 @@ import hashlib ...@@ -6,13 +6,12 @@ import hashlib
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from pytz import UTC from pytz import UTC
from unittest import skipUnless
from django.conf import settings
from django.test import TestCase from django.test import TestCase
from ..image_helpers import get_profile_image_urls_for_user from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from ..image_helpers import get_profile_image_urls_for_user
TEST_SIZES = {'full': 50, 'small': 10} TEST_SIZES = {'full': 50, 'small': 10}
TEST_PROFILE_IMAGE_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo=UTC) TEST_PROFILE_IMAGE_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo=UTC)
...@@ -20,7 +19,7 @@ TEST_PROFILE_IMAGE_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo= ...@@ -20,7 +19,7 @@ TEST_PROFILE_IMAGE_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo=
@attr(shard=2) @attr(shard=2)
@patch.dict('openedx.core.djangoapps.user_api.accounts.image_helpers.PROFILE_IMAGE_SIZES_MAP', TEST_SIZES, clear=True) @patch.dict('openedx.core.djangoapps.user_api.accounts.image_helpers.PROFILE_IMAGE_SIZES_MAP', TEST_SIZES, clear=True)
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class ProfileImageUrlTestCase(TestCase): class ProfileImageUrlTestCase(TestCase):
""" """
Tests for profile image URL generation helpers. Tests for profile image URL generation helpers.
......
...@@ -12,7 +12,6 @@ import json ...@@ -12,7 +12,6 @@ import json
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from pytz import UTC from pytz import UTC
import unittest
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
...@@ -25,7 +24,7 @@ from student.tests.factories import UserFactory ...@@ -25,7 +24,7 @@ from student.tests.factories import UserFactory
from student.models import UserProfile, LanguageProficiency, PendingEmailChange from student.models import UserProfile, LanguageProficiency, PendingEmailChange
from openedx.core.djangoapps.user_api.accounts import ACCOUNT_VISIBILITY_PREF_KEY from openedx.core.djangoapps.user_api.accounts import ACCOUNT_VISIBILITY_PREF_KEY
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from .. import PRIVATE_VISIBILITY, ALL_USERS_VISIBILITY from .. import PRIVATE_VISIBILITY, ALL_USERS_VISIBILITY
TEST_PROFILE_IMAGE_UPLOADED_AT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo=UTC) TEST_PROFILE_IMAGE_UPLOADED_AT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo=UTC)
...@@ -140,7 +139,7 @@ class UserAPITestCase(APITestCase): ...@@ -140,7 +139,7 @@ class UserAPITestCase(APITestCase):
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS') @skip_unless_lms
@attr(shard=2) @attr(shard=2)
class TestOwnUsernameAPI(CacheIsolationTestCase, UserAPITestCase): class TestOwnUsernameAPI(CacheIsolationTestCase, UserAPITestCase):
""" """
...@@ -193,7 +192,7 @@ class TestOwnUsernameAPI(CacheIsolationTestCase, UserAPITestCase): ...@@ -193,7 +192,7 @@ class TestOwnUsernameAPI(CacheIsolationTestCase, UserAPITestCase):
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS') @skip_unless_lms
@patch('openedx.core.djangoapps.user_api.accounts.image_helpers._PROFILE_IMAGE_SIZES', [50, 10]) @patch('openedx.core.djangoapps.user_api.accounts.image_helpers._PROFILE_IMAGE_SIZES', [50, 10])
@patch.dict( @patch.dict(
'openedx.core.djangoapps.user_api.accounts.image_helpers.PROFILE_IMAGE_SIZES_MAP', 'openedx.core.djangoapps.user_api.accounts.image_helpers.PROFILE_IMAGE_SIZES_MAP',
...@@ -783,7 +782,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): ...@@ -783,7 +782,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestAccountAPITransactions(TransactionTestCase): class TestAccountAPITransactions(TransactionTestCase):
""" """
Tests the transactional behavior of the account API Tests the transactional behavior of the account API
......
...@@ -49,6 +49,8 @@ class Command(BaseCommand): ...@@ -49,6 +49,8 @@ class Command(BaseCommand):
# Fields output in the CSV # Fields output in the CSV
OUTPUT_FIELD_NAMES = [ OUTPUT_FIELD_NAMES = [
"user_id",
"username",
"email", "email",
"full_name", "full_name",
"course_id", "course_id",
...@@ -199,6 +201,8 @@ class Command(BaseCommand): ...@@ -199,6 +201,8 @@ class Command(BaseCommand):
query = ( query = (
u""" u"""
SELECT SELECT
user.`id` AS `user_id`,
user.`username` AS username,
user.`email` AS `email`, user.`email` AS `email`,
profile.`name` AS `full_name`, profile.`name` AS `full_name`,
enrollment.`course_id` AS `course_id`, enrollment.`course_id` AS `course_id`,
...@@ -234,8 +238,10 @@ class Command(BaseCommand): ...@@ -234,8 +238,10 @@ class Command(BaseCommand):
cursor.execute(query) cursor.execute(query)
row_count = 0 row_count = 0
for row in self._iterate_results(cursor): for row in self._iterate_results(cursor):
email, full_name, course_id, is_opted_in, pref_set_datetime = row user_id, username, email, full_name, course_id, is_opted_in, pref_set_datetime = row
writer.writerow({ writer.writerow({
"user_id": user_id,
"username": username.encode('utf-8'),
"email": email.encode('utf-8'), "email": email.encode('utf-8'),
# There should not be a case where users are without full_names. We only need this safe check because # There should not be a case where users are without full_names. We only need this safe check because
# of ECOM-1995. # of ECOM-1995.
......
...@@ -6,10 +6,8 @@ import shutil ...@@ -6,10 +6,8 @@ import shutil
import csv import csv
from collections import defaultdict from collections import defaultdict
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from unittest import skipUnless
import ddt import ddt
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.management.base import CommandError from django.core.management.base import CommandError
...@@ -21,11 +19,12 @@ from student.models import CourseEnrollment ...@@ -21,11 +19,12 @@ from student.models import CourseEnrollment
from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in
from openedx.core.djangoapps.user_api.models import UserOrgTag from openedx.core.djangoapps.user_api.models import UserOrgTag
from openedx.core.djangoapps.user_api.management.commands import email_opt_in_list from openedx.core.djangoapps.user_api.management.commands import email_opt_in_list
from openedx.core.djangolib.testing.utils import skip_unless_lms
@attr(shard=2) @attr(shard=2)
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class EmailOptInListTest(ModuleStoreTestCase): class EmailOptInListTest(ModuleStoreTestCase):
"""Tests for the email opt-in list management command. """ """Tests for the email opt-in list management command. """
...@@ -37,6 +36,8 @@ class EmailOptInListTest(ModuleStoreTestCase): ...@@ -37,6 +36,8 @@ class EmailOptInListTest(ModuleStoreTestCase):
OUTPUT_FILE_NAME = "test_org_email_opt_in.csv" OUTPUT_FILE_NAME = "test_org_email_opt_in.csv"
OUTPUT_FIELD_NAMES = [ OUTPUT_FIELD_NAMES = [
"user_id",
"username",
"email", "email",
"full_name", "full_name",
"course_id", "course_id",
...@@ -401,6 +402,8 @@ class EmailOptInListTest(ModuleStoreTestCase): ...@@ -401,6 +402,8 @@ class EmailOptInListTest(ModuleStoreTestCase):
# Check the header row # Check the header row
self.assertEqual({ self.assertEqual({
"user_id": "user_id",
"username": "username",
"email": "email", "email": "email",
"full_name": "full_name", "full_name": "full_name",
"course_id": "course_id", "course_id": "course_id",
...@@ -411,6 +414,8 @@ class EmailOptInListTest(ModuleStoreTestCase): ...@@ -411,6 +414,8 @@ class EmailOptInListTest(ModuleStoreTestCase):
# Check data rows # Check data rows
for user, course_id, opt_in_pref in args: for user, course_id, opt_in_pref in args:
self.assertIn({ self.assertIn({
"user_id": str(user.id),
"username": user.username.encode('utf-8'),
"email": user.email.encode('utf-8'), "email": user.email.encode('utf-8'),
"full_name": ( "full_name": (
user.profile.name.encode('utf-8') user.profile.name.encode('utf-8')
......
...@@ -4,17 +4,15 @@ Unit tests for preference APIs. ...@@ -4,17 +4,15 @@ Unit tests for preference APIs.
""" """
import datetime import datetime
import ddt import ddt
import unittest
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from pytz import common_timezones, utc from pytz import common_timezones, utc
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.test.utils import override_settings from django.test.utils import override_settings
from dateutil.parser import parse as parse_datetime from dateutil.parser import parse as parse_datetime
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from openedx.core.lib.time_zone_utils import get_display_time_zone from openedx.core.lib.time_zone_utils import get_display_time_zone
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
...@@ -42,7 +40,7 @@ from ...preferences.api import ( ...@@ -42,7 +40,7 @@ from ...preferences.api import (
@attr(shard=2) @attr(shard=2)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS') @skip_unless_lms
class TestPreferenceAPI(CacheIsolationTestCase): class TestPreferenceAPI(CacheIsolationTestCase):
""" """
These tests specifically cover the parts of the API methods that are not covered by test_views.py. These tests specifically cover the parts of the API methods that are not covered by test_views.py.
......
...@@ -3,17 +3,16 @@ ...@@ -3,17 +3,16 @@
Unit tests for preference APIs. Unit tests for preference APIs.
""" """
import unittest
import ddt import ddt
import json import json
from mock import patch from mock import patch
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.conf import settings
from django.test.testcases import TransactionTestCase from django.test.testcases import TransactionTestCase
from rest_framework.test import APIClient from rest_framework.test import APIClient
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ...accounts.tests.test_views import UserAPITestCase from ...accounts.tests.test_views import UserAPITestCase
from ..api import set_user_preference from ..api import set_user_preference
from .test_api import get_expected_validation_developer_message, get_expected_key_error_user_message from .test_api import get_expected_validation_developer_message, get_expected_key_error_user_message
...@@ -22,7 +21,7 @@ TOO_LONG_PREFERENCE_KEY = u"x" * 256 ...@@ -22,7 +21,7 @@ TOO_LONG_PREFERENCE_KEY = u"x" * 256
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestPreferencesAPI(UserAPITestCase): class TestPreferencesAPI(UserAPITestCase):
""" """
Unit tests /api/user/v1/accounts/{username}/ Unit tests /api/user/v1/accounts/{username}/
...@@ -316,7 +315,7 @@ class TestPreferencesAPI(UserAPITestCase): ...@@ -316,7 +315,7 @@ class TestPreferencesAPI(UserAPITestCase):
) )
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestPreferencesAPITransactions(TransactionTestCase): class TestPreferencesAPITransactions(TransactionTestCase):
""" """
Tests the transactional behavior of the preferences API Tests the transactional behavior of the preferences API
...@@ -363,7 +362,7 @@ class TestPreferencesAPITransactions(TransactionTestCase): ...@@ -363,7 +362,7 @@ class TestPreferencesAPITransactions(TransactionTestCase):
@ddt.ddt @ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class TestPreferencesDetailAPI(UserAPITestCase): class TestPreferencesDetailAPI(UserAPITestCase):
""" """
Unit tests /api/user/v1/accounts/{username}/{preference_key} Unit tests /api/user/v1/accounts/{username}/{preference_key}
......
...@@ -21,7 +21,7 @@ from social.apps.django_app.default.models import UserSocialAuth ...@@ -21,7 +21,7 @@ from social.apps.django_app.default.models import UserSocialAuth
from django_comment_common import models from django_comment_common import models
from openedx.core.lib.api.test_utils import ApiTestCase, TEST_API_KEY from openedx.core.lib.api.test_utils import ApiTestCase, TEST_API_KEY
from openedx.core.lib.time_zone_utils import get_display_time_zone from openedx.core.lib.time_zone_utils import get_display_time_zone
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin
from third_party_auth.tests.utils import ( from third_party_auth.tests.utils import (
...@@ -541,7 +541,7 @@ class PreferenceUsersListViewTest(UserApiTestCase): ...@@ -541,7 +541,7 @@ class PreferenceUsersListViewTest(UserApiTestCase):
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class LoginSessionViewTest(UserAPITestCase): class LoginSessionViewTest(UserAPITestCase):
"""Tests for the login end-points of the user API. """ """Tests for the login end-points of the user API. """
...@@ -713,7 +713,7 @@ class LoginSessionViewTest(UserAPITestCase): ...@@ -713,7 +713,7 @@ class LoginSessionViewTest(UserAPITestCase):
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class PasswordResetViewTest(UserAPITestCase): class PasswordResetViewTest(UserAPITestCase):
"""Tests of the user API's password reset endpoint. """ """Tests of the user API's password reset endpoint. """
...@@ -771,7 +771,7 @@ class PasswordResetViewTest(UserAPITestCase): ...@@ -771,7 +771,7 @@ class PasswordResetViewTest(UserAPITestCase):
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase):
"""Tests for the registration end-points of the User API. """ """Tests for the registration end-points of the User API. """
...@@ -1925,7 +1925,7 @@ class TestGoogleRegistrationView( ...@@ -1925,7 +1925,7 @@ class TestGoogleRegistrationView(
@ddt.ddt @ddt.ddt
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skip_unless_lms
class UpdateEmailOptInTestCase(UserAPITestCase, SharedModuleStoreTestCase): class UpdateEmailOptInTestCase(UserAPITestCase, SharedModuleStoreTestCase):
"""Tests the UpdateEmailOptInPreference view. """ """Tests the UpdateEmailOptInPreference view. """
......
...@@ -9,6 +9,7 @@ Utility classes for testing django applications. ...@@ -9,6 +9,7 @@ Utility classes for testing django applications.
""" """
import copy import copy
from unittest import skipUnless
import crum import crum
from django import db from django import db
...@@ -175,3 +176,17 @@ def get_mock_request(user=None): ...@@ -175,3 +176,17 @@ def get_mock_request(user=None):
request.get_host = lambda: "edx.org" request.get_host = lambda: "edx.org"
crum.set_current_request(request) crum.set_current_request(request)
return request return request
def skip_unless_cms(func):
"""
Only run the decorated test in the CMS test suite
"""
return skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in CMS')(func)
def skip_unless_lms(func):
"""
Only run the decorated test in the LMS test suite
"""
return skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS')(func)
...@@ -49,7 +49,7 @@ edx-django-sites-extensions==2.1.1 ...@@ -49,7 +49,7 @@ edx-django-sites-extensions==2.1.1
edx-enterprise==0.9.0 edx-enterprise==0.9.0
edx-oauth2-provider==1.2.0 edx-oauth2-provider==1.2.0
edx-opaque-keys==0.4.0 edx-opaque-keys==0.4.0
edx-organizations==0.4.1 edx-organizations==0.4.2
edx-rest-api-client==1.6.0 edx-rest-api-client==1.6.0
edx-search==0.1.2 edx-search==0.1.2
facebook-sdk==0.4.0 facebook-sdk==0.4.0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment