PY-2016.1.4 <alisantang@C02RP0YSG8WM.tld Merge branch 'master'

This commit is contained in:
alisan617
2016-06-20 19:51:20 -04:00
43 changed files with 1532 additions and 1226 deletions

View File

@@ -26,6 +26,8 @@ omit =
openedx/core/djangoapps/*/migrations/*
openedx/core/djangoapps/debug/*
concurrency=multiprocessing
[report]
ignore_errors = True

View File

@@ -1,4 +1,6 @@
**/vendor
cms/static/cms/js/build.js
cms/static/cms/js/spec/main.js
cms/static/js/i18n/**/*.js
lms/static/js/i18n/**/*.js
lms/static/lms/js/build.js

View File

@@ -1,8 +1,8 @@
(function () {
(function() {
'use strict';
var commonLibrariesPath = 'common/js/common_libraries';
var getModule = function (moduleName, excludeCommonDeps) {
var getModule = function(moduleName, excludeCommonDeps) {
var module = {
name: moduleName
};
@@ -14,7 +14,7 @@
return module;
};
var getModulesList = function (modules) {
var getModulesList = function(modules) {
var result = [getModule(commonLibrariesPath)];
return result.concat(modules.map(function (moduleName) {
return getModule(moduleName, true);
@@ -92,7 +92,7 @@
/**
* Stub out requireJS text in the optimized file, but leave available for non-optimized development use.
*/
stubModules: ["text"],
stubModules: ['text'],
/**
* If shim config is used in the app during runtime, duplicate the config
@@ -170,4 +170,4 @@
*/
logLevel: 1
};
} ())
}())

View File

@@ -1,5 +1,6 @@
;(function (require, define) {
;(function(require, define) {
'use strict';
if (window) {
// MathJax Fast Preview was introduced in 2.5. However, it
// causes undesirable flashing/font size changes when
@@ -16,300 +17,300 @@
// needs to be served. To handle this, we load the correct file in the
// rendered template and then use this to ensure that RequireJS knows
// how to find it.
define("gettext", function () { return window.gettext; });
define('gettext', function() { return window.gettext; });
}
require.config({
// NOTE: baseUrl has been previously set in cms/static/templates/base.html
waitSeconds: 60,
paths: {
"domReady": "js/vendor/domReady",
"mustache": "js/vendor/mustache",
"codemirror": "js/vendor/codemirror-compressed",
"codemirror/stex": "js/vendor/CodeMirror/stex",
"jquery": "common/js/vendor/jquery",
"jquery-migrate": "common/js/vendor/jquery-migrate",
"jquery.ui": "js/vendor/jquery-ui.min",
"jquery.form": "js/vendor/jquery.form",
"jquery.markitup": "js/vendor/markitup/jquery.markitup",
"jquery.leanModal": "js/vendor/jquery.leanModal",
"jquery.ajaxQueue": "js/vendor/jquery.ajaxQueue",
"jquery.smoothScroll": "js/vendor/jquery.smooth-scroll.min",
"jquery.timepicker": "js/vendor/timepicker/jquery.timepicker",
"jquery.cookie": "js/vendor/jquery.cookie",
"jquery.qtip": "js/vendor/jquery.qtip.min",
"jquery.scrollTo": "common/js/vendor/jquery.scrollTo",
"jquery.flot": "js/vendor/flot/jquery.flot.min",
"jquery.fileupload": "js/vendor/jQuery-File-Upload/js/jquery.fileupload",
"jquery.fileupload-process": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-process",
"jquery.fileupload-validate": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate",
"jquery.iframe-transport": "js/vendor/jQuery-File-Upload/js/jquery.iframe-transport",
"jquery.inputnumber": "js/vendor/html5-input-polyfills/number-polyfill",
"jquery.immediateDescendents": "coffee/src/jquery.immediateDescendents",
"datepair": "js/vendor/timepicker/datepair",
"date": "js/vendor/date",
"moment": "js/vendor/moment.min",
"moment-with-locales": "js/vendor/moment-with-locales.min",
"text": 'js/vendor/requirejs/text',
"underscore": "common/js/vendor/underscore",
"underscore.string": "common/js/vendor/underscore.string",
"backbone": "common/js/vendor/backbone",
"backbone-relational" : "js/vendor/backbone-relational.min",
"backbone.associations": "js/vendor/backbone-associations-min",
"backbone.paginator": "common/js/vendor/backbone.paginator",
"tinymce": "js/vendor/tinymce/js/tinymce/tinymce.full.min",
"jquery.tinymce": "js/vendor/tinymce/js/tinymce/jquery.tinymce.min",
"xmodule": "/xmodule/xmodule",
"xblock/core": "js/xblock/core",
"xblock": "coffee/src/xblock",
"utility": "js/src/utility",
"accessibility": "js/src/accessibility_tools",
"URI": "js/vendor/URI.min",
"ieshim": "js/src/ie_shim",
"tooltip_manager": "js/src/tooltip_manager",
"modernizr": "edx-pattern-library/js/modernizr-custom",
"afontgarde": "edx-pattern-library/js/afontgarde",
"edxicons": "edx-pattern-library/js/edx-icons",
"draggabilly": "js/vendor/draggabilly",
'domReady': 'js/vendor/domReady',
'mustache': 'js/vendor/mustache',
'codemirror': 'js/vendor/codemirror-compressed',
'codemirror/stex': 'js/vendor/CodeMirror/stex',
'jquery': 'common/js/vendor/jquery',
'jquery-migrate': 'common/js/vendor/jquery-migrate',
'jquery.ui': 'js/vendor/jquery-ui.min',
'jquery.form': 'js/vendor/jquery.form',
'jquery.markitup': 'js/vendor/markitup/jquery.markitup',
'jquery.leanModal': 'js/vendor/jquery.leanModal',
'jquery.ajaxQueue': 'js/vendor/jquery.ajaxQueue',
'jquery.smoothScroll': 'js/vendor/jquery.smooth-scroll.min',
'jquery.timepicker': 'js/vendor/timepicker/jquery.timepicker',
'jquery.cookie': 'js/vendor/jquery.cookie',
'jquery.qtip': 'js/vendor/jquery.qtip.min',
'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo',
'jquery.flot': 'js/vendor/flot/jquery.flot.min',
'jquery.fileupload': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload',
'jquery.fileupload-process': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload-process',
'jquery.fileupload-validate': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate',
'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
'jquery.inputnumber': 'js/vendor/html5-input-polyfills/number-polyfill',
'jquery.immediateDescendents': 'coffee/src/jquery.immediateDescendents',
'datepair': 'js/vendor/timepicker/datepair',
'date': 'js/vendor/date',
'moment': 'js/vendor/moment.min',
'moment-with-locales': 'js/vendor/moment-with-locales.min',
'text': 'js/vendor/requirejs/text',
'underscore': 'common/js/vendor/underscore',
'underscore.string': 'common/js/vendor/underscore.string',
'backbone': 'common/js/vendor/backbone',
'backbone-relational': 'js/vendor/backbone-relational.min',
'backbone.associations': 'js/vendor/backbone-associations-min',
'backbone.paginator': 'common/js/vendor/backbone.paginator',
'tinymce': 'js/vendor/tinymce/js/tinymce/tinymce.full.min',
'jquery.tinymce': 'js/vendor/tinymce/js/tinymce/jquery.tinymce.min',
'xmodule': '/xmodule/xmodule',
'xblock/cms.runtime.v1': 'cms/js/xblock/cms.runtime.v1',
'xblock': 'common/js/xblock',
'utility': 'js/src/utility',
'accessibility': 'js/src/accessibility_tools',
'URI': 'js/vendor/URI.min',
'ieshim': 'js/src/ie_shim',
'tooltip_manager': 'js/src/tooltip_manager',
'modernizr': 'edx-pattern-library/js/modernizr-custom',
'afontgarde': 'edx-pattern-library/js/afontgarde',
'edxicons': 'edx-pattern-library/js/edx-icons',
'draggabilly': 'js/vendor/draggabilly',
// Files needed for Annotations feature
"annotator": "js/vendor/ova/annotator-full",
"annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth",
"video.dev": "js/vendor/ova/video.dev",
"vjs.youtube": 'js/vendor/ova/vjs.youtube',
"rangeslider": 'js/vendor/ova/rangeslider',
"share-annotator": 'js/vendor/ova/share-annotator',
"richText-annotator": 'js/vendor/ova/richText-annotator',
"reply-annotator": 'js/vendor/ova/reply-annotator',
"grouping-annotator": 'js/vendor/ova/grouping-annotator',
"tags-annotator": 'js/vendor/ova/tags-annotator',
"diacritic-annotator": 'js/vendor/ova/diacritic-annotator',
"flagging-annotator": 'js/vendor/ova/flagging-annotator',
"jquery-Watch": 'js/vendor/ova/jquery-Watch',
"openseadragon": 'js/vendor/ova/openseadragon',
"osda": 'js/vendor/ova/OpenSeaDragonAnnotation',
"ova": 'js/vendor/ova/ova',
"catch": 'js/vendor/ova/catch/js/catch',
"handlebars": 'js/vendor/ova/catch/js/handlebars-1.1.2',
"lang_edx": "js/src/lang_edx",
'annotator': 'js/vendor/ova/annotator-full',
'annotator-harvardx': 'js/vendor/ova/annotator-full-firebase-auth',
'video.dev': 'js/vendor/ova/video.dev',
'vjs.youtube': 'js/vendor/ova/vjs.youtube',
'rangeslider': 'js/vendor/ova/rangeslider',
'share-annotator': 'js/vendor/ova/share-annotator',
'richText-annotator': 'js/vendor/ova/richText-annotator',
'reply-annotator': 'js/vendor/ova/reply-annotator',
'grouping-annotator': 'js/vendor/ova/grouping-annotator',
'tags-annotator': 'js/vendor/ova/tags-annotator',
'diacritic-annotator': 'js/vendor/ova/diacritic-annotator',
'flagging-annotator': 'js/vendor/ova/flagging-annotator',
'jquery-Watch': 'js/vendor/ova/jquery-Watch',
'openseadragon': 'js/vendor/ova/openseadragon',
'osda': 'js/vendor/ova/OpenSeaDragonAnnotation',
'ova': 'js/vendor/ova/ova',
'catch': 'js/vendor/ova/catch/js/catch',
'handlebars': 'js/vendor/ova/catch/js/handlebars-1.1.2',
'lang_edx': 'js/src/lang_edx',
// end of Annotation tool files
// externally hosted files
"mathjax": "//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured", // jshint ignore:line
"youtube": [
// youtube URL does not end in ".js". We add "?noext" to the path so
// that require.js adds the ".js" to the query component of the URL,
'mathjax': '//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // jshint ignore:line
'youtube': [
// youtube URL does not end in '.js'. We add '?noext' to the path so
// that require.js adds the '.js' to the query component of the URL,
// and leaves the path component intact.
"//www.youtube.com/player_api?noext",
'//www.youtube.com/player_api?noext',
// if youtube fails to load, fallback on a local file
// so that require doesn't fall over
"js/src/youtube_fallback"
'js/src/youtube_fallback'
]
},
shim: {
"gettext": {
exports: "gettext"
'gettext': {
exports: 'gettext'
},
"date": {
exports: "Date"
'date': {
exports: 'Date'
},
"jquery-migrate": ['jquery'],
"jquery.ui": {
deps: ["jquery"],
exports: "jQuery.ui"
'jquery-migrate': ['jquery'],
'jquery.ui': {
deps: ['jquery'],
exports: 'jQuery.ui'
},
"jquery.form": {
deps: ["jquery"],
exports: "jQuery.fn.ajaxForm"
'jquery.form': {
deps: ['jquery'],
exports: 'jQuery.fn.ajaxForm'
},
"jquery.markitup": {
deps: ["jquery"],
exports: "jQuery.fn.markitup"
'jquery.markitup': {
deps: ['jquery'],
exports: 'jQuery.fn.markitup'
},
"jquery.leanmodal": {
deps: ["jquery"],
exports: "jQuery.fn.leanModal"
'jquery.leanmodal': {
deps: ['jquery'],
exports: 'jQuery.fn.leanModal'
},
"jquery.ajaxQueue": {
deps: ["jquery"],
exports: "jQuery.fn.ajaxQueue"
'jquery.ajaxQueue': {
deps: ['jquery'],
exports: 'jQuery.fn.ajaxQueue'
},
"jquery.smoothScroll": {
deps: ["jquery"],
exports: "jQuery.fn.smoothScroll"
'jquery.smoothScroll': {
deps: ['jquery'],
exports: 'jQuery.fn.smoothScroll'
},
"jquery.cookie": {
deps: ["jquery"],
exports: "jQuery.fn.cookie"
'jquery.cookie': {
deps: ['jquery'],
exports: 'jQuery.fn.cookie'
},
"jquery.qtip": {
deps: ["jquery"],
exports: "jQuery.fn.qtip"
'jquery.qtip': {
deps: ['jquery'],
exports: 'jQuery.fn.qtip'
},
"jquery.scrollTo": {
deps: ["jquery"],
exports: "jQuery.fn.scrollTo"
'jquery.scrollTo': {
deps: ['jquery'],
exports: 'jQuery.fn.scrollTo'
},
"jquery.flot": {
deps: ["jquery"],
exports: "jQuery.fn.plot"
'jquery.flot': {
deps: ['jquery'],
exports: 'jQuery.fn.plot'
},
"jquery.fileupload": {
deps: ["jquery.ui", "jquery.iframe-transport"],
exports: "jQuery.fn.fileupload"
'jquery.fileupload': {
deps: ['jquery.ui', 'jquery.iframe-transport'],
exports: 'jQuery.fn.fileupload'
},
"jquery.fileupload-process": {
deps: ["jquery.fileupload"]
'jquery.fileupload-process': {
deps: ['jquery.fileupload']
},
"jquery.fileupload-validate": {
deps: ["jquery.fileupload"]
'jquery.fileupload-validate': {
deps: ['jquery.fileupload']
},
"jquery.inputnumber": {
deps: ["jquery"],
exports: "jQuery.fn.inputNumber"
'jquery.inputnumber': {
deps: ['jquery'],
exports: 'jQuery.fn.inputNumber'
},
"jquery.tinymce": {
deps: ["jquery", "tinymce"],
exports: "jQuery.fn.tinymce"
'jquery.tinymce': {
deps: ['jquery', 'tinymce'],
exports: 'jQuery.fn.tinymce'
},
"datepair": {
deps: ["jquery.ui", "jquery.timepicker"]
'datepair': {
deps: ['jquery.ui', 'jquery.timepicker']
},
"underscore": {
exports: "_"
'underscore': {
exports: '_'
},
"backbone": {
deps: ["underscore", "jquery"],
exports: "Backbone"
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
"backbone.associations": {
deps: ["backbone"],
exports: "Backbone.Associations"
'backbone.associations': {
deps: ['backbone'],
exports: 'Backbone.Associations'
},
"backbone.paginator": {
deps: ["backbone"],
exports: "Backbone.PageableCollection"
'backbone.paginator': {
deps: ['backbone'],
exports: 'Backbone.PageableCollection'
},
"youtube": {
exports: "YT"
'youtube': {
exports: 'YT'
},
"codemirror": {
exports: "CodeMirror"
'codemirror': {
exports: 'CodeMirror'
},
"codemirror/stex": {
deps: ["codemirror"]
'codemirror/stex': {
deps: ['codemirror']
},
"tinymce": {
exports: "tinymce"
'tinymce': {
exports: 'tinymce'
},
"lang_edx": {
deps: ["jquery"]
'lang_edx': {
deps: ['jquery']
},
"mathjax": {
exports: "MathJax",
'mathjax': {
exports: 'MathJax',
init: function() {
window.MathJax.Hub.Config({
tex2jax: {
inlineMath: [
["\\(","\\)"],
['\\(','\\)'],
['[mathjaxinline]','[/mathjaxinline]']
],
displayMath: [
["\\[","\\]"],
['\\[','\\]'],
['[mathjax]','[/mathjax]']
]
}
});
// In order to eliminate all flashing during interactive
// preview, it is necessary to set processSectionDelay to 0
// (remove delay between input and output phases). This
// effectively disables fast preview, regardless of
// the fast preview setting as shown in the context menu.
window.MathJax.Hub.processSectionDelay = 0;
window.MathJax.Hub.Configured();
});
// In order to eliminate all flashing during interactive
// preview, it is necessary to set processSectionDelay to 0
// (remove delay between input and output phases). This
// effectively disables fast preview, regardless of
// the fast preview setting as shown in the context menu.
window.MathJax.Hub.processSectionDelay = 0;
window.MathJax.Hub.Configured();
}
},
"URI": {
exports: "URI"
'URI': {
exports: 'URI'
},
"tooltip_manager": {
deps: ["jquery", "underscore"]
'tooltip_manager': {
deps: ['jquery', 'underscore']
},
"jquery.immediateDescendents": {
deps: ["jquery"]
'jquery.immediateDescendents': {
deps: ['jquery']
},
"xblock/core": {
exports: "XBlock",
deps: ["jquery", "jquery.immediateDescendents"]
'xblock/core': {
exports: 'XBlock',
deps: ['jquery', 'jquery.immediateDescendents']
},
"xblock/runtime.v1": {
exports: "XBlock",
deps: ["xblock/core"]
'xblock/runtime.v1': {
exports: 'XBlock',
deps: ['xblock/core']
},
"coffee/src/main": {
deps: ["coffee/src/ajax_prefix"]
'coffee/src/main': {
deps: ['coffee/src/ajax_prefix']
},
"js/src/logger": {
exports: "Logger",
deps: ["coffee/src/ajax_prefix"]
'js/src/logger': {
exports: 'Logger',
deps: ['coffee/src/ajax_prefix']
},
"modernizr": {
exports: "Modernizr"
'modernizr': {
exports: 'Modernizr'
},
"afontgarde": {
exports: "AFontGarde"
'afontgarde': {
exports: 'AFontGarde'
},
// the following are all needed for annotation tools
"video.dev": {
exports:"videojs"
'video.dev': {
exports: 'videojs'
},
"vjs.youtube": {
deps: ["video.dev"]
'vjs.youtube': {
deps: ['video.dev']
},
"rangeslider": {
deps: ["video.dev"]
'rangeslider': {
deps: ['video.dev']
},
"annotator": {
exports: "Annotator"
'annotator': {
exports: 'Annotator'
},
"annotator-harvardx":{
deps: ["annotator"]
'annotator-harvardx': {
deps: ['annotator']
},
"share-annotator": {
deps: ["annotator"]
'share-annotator': {
deps: ['annotator']
},
"richText-annotator": {
deps: ["annotator", "tinymce"]
'richText-annotator': {
deps: ['annotator', 'tinymce']
},
"reply-annotator": {
deps: ["annotator"]
'reply-annotator': {
deps: ['annotator']
},
"tags-annotator": {
deps: ["annotator"]
'tags-annotator': {
deps: ['annotator']
},
"diacritic-annotator": {
deps: ["annotator"]
'diacritic-annotator': {
deps: ['annotator']
},
"flagging-annotator": {
deps: ["annotator"]
'flagging-annotator': {
deps: ['annotator']
},
"grouping-annotator": {
deps: ["annotator"]
'grouping-annotator': {
deps: ['annotator']
},
"ova":{
exports: "ova",
deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube",
"rangeslider", "share-annotator", "richText-annotator", "reply-annotator",
"tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator",
"jquery-Watch", "catch", "handlebars", "URI"]
'ova': {
exports: 'ova',
deps: ['annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube',
'rangeslider', 'share-annotator', 'richText-annotator', 'reply-annotator',
'tags-annotator', 'flagging-annotator', 'grouping-annotator', 'diacritic-annotator',
'jquery-Watch', 'catch', 'handlebars', 'URI']
},
"osda":{
exports: "osda",
deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube",
"rangeslider", "share-annotator", "richText-annotator", "reply-annotator",
"tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator",
"openseadragon", "jquery-Watch", "catch", "handlebars", "URI"]
'osda': {
exports: 'osda',
deps: ['annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube',
'rangeslider', 'share-annotator', 'richText-annotator', 'reply-annotator',
'tags-annotator', 'flagging-annotator', 'grouping-annotator', 'diacritic-annotator',
'openseadragon', 'jquery-Watch', 'catch', 'handlebars', 'URI']
}
// end of annotation tool files
}

View File

@@ -0,0 +1,299 @@
(function(requirejs, requireSerial) {
'use strict';
var i, specHelpers, testFiles;
requirejs.config({
baseUrl: '/base/',
paths: {
'gettext': 'xmodule_js/common_static/js/test/i18n',
'mustache': 'xmodule_js/common_static/js/vendor/mustache',
'codemirror': 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror',
'jquery': 'xmodule_js/common_static/common/js/vendor/jquery',
'jquery-migrate': 'xmodule_js/common_static/common/js/vendor/jquery-migrate',
'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min',
'jquery.form': 'xmodule_js/common_static/js/vendor/jquery.form',
'jquery.markitup': 'xmodule_js/common_static/js/vendor/markitup/jquery.markitup',
'jquery.leanModal': 'xmodule_js/common_static/js/vendor/jquery.leanModal',
'jquery.ajaxQueue': 'xmodule_js/common_static/js/vendor/jquery.ajaxQueue',
'jquery.smoothScroll': 'xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min',
'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo',
'jquery.timepicker': 'xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker',
'jquery.cookie': 'xmodule_js/common_static/js/vendor/jquery.cookie',
'jquery.qtip': 'xmodule_js/common_static/js/vendor/jquery.qtip.min',
'jquery.fileupload': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload',
'jquery.fileupload-process': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process', // jshint ignore:line
'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // jshint ignore:line
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // jshint ignore:line
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate',
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
'date': 'xmodule_js/common_static/js/vendor/date',
'moment': 'xmodule_js/common_static/js/vendor/moment.min',
'moment-with-locales': 'xmodule_js/common_static/js/vendor/moment-with-locales.min',
'text': 'xmodule_js/common_static/js/vendor/requirejs/text',
'underscore': 'common/js/vendor/underscore',
'underscore.string': 'common/js/vendor/underscore.string',
'backbone': 'common/js/vendor/backbone',
'backbone.associations': 'xmodule_js/common_static/js/vendor/backbone-associations-min',
'backbone.paginator': 'common/js/vendor/backbone.paginator',
'backbone-relational': 'xmodule_js/common_static/js/vendor/backbone-relational.min',
'tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min',
'jquery.tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce',
'xmodule': 'xmodule_js/src/xmodule',
'xblock/cms.runtime.v1': 'cms/js/xblock/cms.runtime.v1',
'xblock': 'common/js/xblock',
'utility': 'xmodule_js/common_static/js/src/utility',
'accessibility': 'xmodule_js/common_static/js/src/accessibility_tools',
'sinon': 'xmodule_js/common_static/js/vendor/sinon-1.17.0',
'squire': 'xmodule_js/common_static/js/vendor/Squire',
'jasmine-imagediff': 'xmodule_js/common_static/js/vendor/jasmine-imagediff',
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly',
'domReady': 'xmodule_js/common_static/js/vendor/domReady',
'URI': 'xmodule_js/common_static/js/vendor/URI.min',
'mock-ajax': 'xmodule_js/common_static/js/vendor/mock-ajax',
'modernizr': 'edx-pattern-library/js/modernizr-custom',
'afontgarde': 'edx-pattern-library/js/afontgarde',
'edxicons': 'edx-pattern-library/js/edx-icons',
'mathjax': '//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // jshint ignore:line
'youtube': '//www.youtube.com/player_api?noext',
'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix',
'js/spec/test_utils': 'js/spec/test_utils'
},
shim: {
'gettext': {
exports: 'gettext'
},
'date': {
exports: 'Date'
},
'jquery-migrate': ['jquery'],
'jquery.ui': {
deps: ['jquery'],
exports: 'jQuery.ui'
},
'jquery.form': {
deps: ['jquery'],
exports: 'jQuery.fn.ajaxForm'
},
'jquery.markitup': {
deps: ['jquery'],
exports: 'jQuery.fn.markitup'
},
'jquery.leanModal': {
deps: ['jquery'],
exports: 'jQuery.fn.leanModal'
},
'jquery.smoothScroll': {
deps: ['jquery'],
exports: 'jQuery.fn.smoothScroll'
},
'jquery.ajaxQueue': {
deps: ['jquery'],
exports: 'jQuery.fn.ajaxQueue'
},
'jquery.scrollTo': {
deps: ['jquery'],
exports: 'jQuery.fn.scrollTo'
},
'jquery.cookie': {
deps: ['jquery'],
exports: 'jQuery.fn.cookie'
},
'jquery.qtip': {
deps: ['jquery'],
exports: 'jQuery.fn.qtip'
},
'jquery.fileupload': {
deps: ['jquery.ui', 'jquery.iframe-transport'],
exports: 'jQuery.fn.fileupload'
},
'jquery.fileupload-process': {
deps: ['jquery.fileupload']
},
'jquery.fileupload-validate': {
deps: ['jquery.fileupload']
},
'jquery.inputnumber': {
deps: ['jquery'],
exports: 'jQuery.fn.inputNumber'
},
'jquery.simulate': {
deps: ['jquery'],
exports: 'jQuery.fn.simulate'
},
'jquery.tinymce': {
deps: ['jquery', 'tinymce'],
exports: 'jQuery.fn.tinymce'
},
'datepair': {
deps: ['jquery.ui', 'jquery.timepicker']
},
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'backbone.associations': {
deps: ['backbone'],
exports: 'Backbone.Associations'
},
'backbone.paginator': {
deps: ['backbone'],
exports: 'Backbone.PageableCollection'
},
'backbone-relational': {
deps: ['backbone']
},
'youtube': {
exports: 'YT'
},
'codemirror': {
exports: 'CodeMirror'
},
'tinymce': {
exports: 'tinymce'
},
'mathjax': {
exports: 'MathJax',
init: function() {
window.MathJax.Hub.Config({
tex2jax: {
inlineMath: [['\\(', '\\)'], ['[mathjaxinline]', '[/mathjaxinline]']],
displayMath: [['\\[', '\\]'], ['[mathjax]', '[/mathjax]']]
}
});
return window.MathJax.Hub.Configured();
}
},
'URI': {
exports: 'URI'
},
'xmodule': {
exports: 'XModule'
},
'sinon': {
exports: 'sinon'
},
'jasmine-imagediff': {},
'common/js/spec_helpers/jasmine-extensions': {
deps: ['jquery']
},
'common/js/spec_helpers/jasmine-stealth': {
deps: ['underscore', 'underscore.string']
},
'common/js/spec_helpers/jasmine-waituntil': {
deps: ['jquery']
},
'xblock/core': {
exports: 'XBlock',
deps: ['jquery', 'jquery.immediateDescendents']
},
'xblock/runtime.v1': {
exports: 'XBlock',
deps: ['xblock/core']
},
'mock-ajax': {
deps: ['jquery']
},
'coffee/src/main': {
deps: ['coffee/src/ajax_prefix']
},
'coffee/src/ajax_prefix': {
deps: ['jquery']
},
'modernizr': {
exports: 'Modernizr'
},
'afontgarde': {
exports: 'AFontGarde'
}
}
});
jasmine.getFixtures().fixturesPath += 'coffee/fixtures';
testFiles = [
'cms/js/spec/xblock/cms.runtime.v1_spec',
'coffee/spec/main_spec',
'coffee/spec/models/course_spec',
'coffee/spec/models/metadata_spec',
'coffee/spec/models/section_spec',
'coffee/spec/models/settings_course_grader_spec',
'coffee/spec/models/settings_grading_spec',
'coffee/spec/models/textbook_spec',
'coffee/spec/models/upload_spec',
'coffee/spec/views/course_info_spec',
'coffee/spec/views/metadata_edit_spec',
'coffee/spec/views/module_edit_spec',
'coffee/spec/views/textbook_spec',
'coffee/spec/views/upload_spec',
'js/spec/video/transcripts/utils_spec',
'js/spec/video/transcripts/editor_spec',
'js/spec/video/transcripts/videolist_spec',
'js/spec/video/transcripts/message_manager_spec',
'js/spec/video/transcripts/file_uploader_spec',
'js/spec/models/component_template_spec',
'js/spec/models/explicit_url_spec',
'js/spec/models/xblock_info_spec',
'js/spec/models/xblock_validation_spec',
'js/spec/models/license_spec',
'js/spec/utils/drag_and_drop_spec',
'js/spec/utils/handle_iframe_binding_spec',
'js/spec/utils/module_spec',
'js/spec/views/active_video_upload_list_spec',
'js/spec/views/previous_video_upload_spec',
'js/spec/views/previous_video_upload_list_spec',
'js/spec/views/assets_spec',
'js/spec/views/baseview_spec',
'js/spec/views/container_spec',
'js/spec/views/paged_container_spec',
'js/spec/views/group_configuration_spec',
'js/spec/views/unit_outline_spec',
'js/spec/views/xblock_spec',
'js/spec/views/xblock_editor_spec',
'js/spec/views/xblock_string_field_editor_spec',
'js/spec/views/xblock_validation_spec',
'js/spec/views/license_spec',
'js/spec/views/paging_spec',
'js/spec/views/login_studio_spec',
'js/spec/views/pages/container_spec',
'js/spec/views/pages/container_subviews_spec',
'js/spec/views/pages/group_configurations_spec',
'js/spec/views/pages/course_outline_spec',
'js/spec/views/pages/course_rerun_spec',
'js/spec/views/pages/index_spec',
'js/spec/views/pages/library_users_spec',
'js/spec/views/modals/base_modal_spec',
'js/spec/views/modals/edit_xblock_spec',
'js/spec/views/modals/validation_error_modal_spec',
'js/spec/views/settings/main_spec',
'js/spec/factories/xblock_validation_spec',
'js/certificates/spec/models/certificate_spec',
'js/certificates/spec/views/certificate_details_spec',
'js/certificates/spec/views/certificate_editor_spec',
'js/certificates/spec/views/certificates_list_spec',
'js/certificates/spec/views/certificate_preview_spec'
];
i = 0;
while (i < testFiles.length) {
testFiles[i] = '/base/' + testFiles[i] + '.js';
i++;
}
specHelpers = [
'common/js/spec_helpers/jasmine-extensions',
'common/js/spec_helpers/jasmine-stealth',
'common/js/spec_helpers/jasmine-waituntil'
];
requireSerial(specHelpers.concat(testFiles), function() {
return window.__karma__.start();
});
}).call(this, requirejs, requireSerial); // jshint ignore:line

View File

@@ -0,0 +1,218 @@
(function(requirejs, requireSerial) {
'use strict';
var i, specHelpers, testFiles;
requirejs.config({
baseUrl: '/base/',
paths: {
'gettext': 'xmodule_js/common_static/js/test/i18n',
'mustache': 'xmodule_js/common_static/js/vendor/mustache',
'codemirror': 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror',
'jquery': 'common/js/vendor/jquery',
'jquery-migrate': 'common/js/vendor/jquery-migrate',
'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min',
'jquery.form': 'xmodule_js/common_static/js/vendor/jquery.form',
'jquery.markitup': 'xmodule_js/common_static/js/vendor/markitup/jquery.markitup',
'jquery.leanModal': 'xmodule_js/common_static/js/vendor/jquery.leanModal',
'jquery.smoothScroll': 'xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min',
'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo',
'jquery.timepicker': 'xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker',
'jquery.cookie': 'xmodule_js/common_static/js/vendor/jquery.cookie',
'jquery.qtip': 'xmodule_js/common_static/js/vendor/jquery.qtip.min',
'jquery.fileupload': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload',
'jquery.fileupload-process': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process', // jshint ignore:line
'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // jshint ignore:line
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // jshint ignore:line
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
'date': 'xmodule_js/common_static/js/vendor/date',
'text': 'xmodule_js/common_static/js/vendor/requirejs/text',
'underscore': 'common/js/vendor/underscore',
'underscore.string': 'common/js/vendor/underscore.string',
'backbone': 'common/js/vendor/backbone',
'backbone.associations': 'xmodule_js/common_static/js/vendor/backbone-associations-min',
'backbone.paginator': 'common/js/vendor/backbone.paginator',
'tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min',
'jquery.tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce',
'xmodule': 'xmodule_js/src/xmodule',
'xblock/cms.runtime.v1': 'cms/js/xblock/cms.runtime.v1',
'xblock': 'common/js/xblock',
'utility': 'xmodule_js/common_static/js/src/utility',
'sinon': 'xmodule_js/common_static/js/vendor/sinon-1.17.0',
'squire': 'xmodule_js/common_static/js/vendor/Squire',
'modernizr': 'edx-pattern-library/js/modernizr-custom',
'afontgarde': 'edx-pattern-library/js/afontgarde',
'edxicons': 'edx-pattern-library/js/edx-icons',
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly',
'domReady': 'xmodule_js/common_static/js/vendor/domReady',
'URI': 'xmodule_js/common_static/js/vendor/URI.min',
'mathjax': '//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // jshint ignore:line
'youtube': '//www.youtube.com/player_api?noext',
'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix'
},
shim: {
'gettext': {
exports: 'gettext'
},
'date': {
exports: 'Date'
},
'jquery.ui': {
deps: ['jquery'],
exports: 'jQuery.ui'
},
'jquery.form': {
deps: ['jquery'],
exports: 'jQuery.fn.ajaxForm'
},
'jquery.markitup': {
deps: ['jquery'],
exports: 'jQuery.fn.markitup'
},
'jquery.leanModal': {
deps: ['jquery'],
exports: 'jQuery.fn.leanModal'
},
'jquery.smoothScroll': {
deps: ['jquery'],
exports: 'jQuery.fn.smoothScroll'
},
'jquery.scrollTo': {
deps: ['jquery'],
exports: 'jQuery.fn.scrollTo'
},
'jquery.cookie': {
deps: ['jquery'],
exports: 'jQuery.fn.cookie'
},
'jquery.qtip': {
deps: ['jquery'],
exports: 'jQuery.fn.qtip'
},
'jquery.fileupload': {
deps: ['jquery.ui', 'jquery.iframe-transport'],
exports: 'jQuery.fn.fileupload'
},
'jquery.fileupload-process': {
deps: ['jquery.fileupload']
},
'jquery.fileupload-validate': {
deps: ['jquery.fileupload']
},
'jquery.inputnumber': {
deps: ['jquery'],
exports: 'jQuery.fn.inputNumber'
},
'jquery.tinymce': {
deps: ['jquery', 'tinymce'],
exports: 'jQuery.fn.tinymce'
},
'datepair': {
deps: ['jquery.ui', 'jquery.timepicker']
},
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'backbone.associations': {
deps: ['backbone'],
exports: 'Backbone.Associations'
},
'backbone.paginator': {
deps: ['backbone'],
exports: 'Backbone.PageableCollection'
},
'youtube': {
exports: 'YT'
},
'codemirror': {
exports: 'CodeMirror'
},
'tinymce': {
exports: 'tinymce'
},
'mathjax': {
exports: 'MathJax',
init: function() {
window.MathJax.Hub.Config({
tex2jax: {
inlineMath: [['\\(', '\\)'], ['[mathjaxinline]', '[/mathjaxinline]']],
displayMath: [['\\[', '\\]'], ['[mathjax]', '[/mathjax]']]
}
});
window.MathJax.Hub.Configured();
}
},
'URI': {
exports: 'URI'
},
'xmodule': {
exports: 'XModule'
},
'sinon': {
exports: 'sinon'
},
'common/js/spec_helpers/jasmine-extensions': {
deps: ['jquery']
},
'common/js/spec_helpers/jasmine-stealth': {
deps: ['underscore', 'underscore.string']
},
'common/js/spec_helpers/jasmine-waituntil': {
deps: ['jquery']
},
'xblock/core': {
exports: 'XBlock',
deps: ['jquery', 'jquery.immediateDescendents']
},
'xblock/runtime.v1': {
exports: 'XBlock',
deps: ['xblock/core']
},
'coffee/src/main': {
deps: ['coffee/src/ajax_prefix']
},
'coffee/src/ajax_prefix': {
deps: ['jquery']
},
'modernizr': {
exports: 'Modernizr'
},
'afontgarde': {
exports: 'AFontGarde'
}
}
});
jasmine.getFixtures().fixturesPath += 'coffee/fixtures';
testFiles = [
'coffee/spec/views/assets_spec',
'js/spec/video/translations_editor_spec',
'js/spec/video/file_uploader_editor_spec',
'js/spec/models/group_configuration_spec'
];
i = 0;
while (i < testFiles.length) {
testFiles[i] = '/base/' + testFiles[i] + '.js';
i++;
}
specHelpers = [
'common/js/spec_helpers/jasmine-extensions',
'common/js/spec_helpers/jasmine-stealth',
'common/js/spec_helpers/jasmine-waituntil'
];
requireSerial(specHelpers.concat(testFiles), function() {
return window.__karma__.start();
});
}).call(this, requirejs, requireSerial); // jshint ignore:line

View File

@@ -1,10 +1,11 @@
define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cms.runtime.v1"],
function (EditHelpers, BaseModal) {
define(['js/spec_helpers/edit_helpers', 'js/views/modals/base_modal', 'xblock/cms.runtime.v1'],
function(EditHelpers, BaseModal) {
'use strict';
describe("Studio Runtime v1", function() {
describe('Studio Runtime v1', function() {
var runtime;
beforeEach(function () {
beforeEach(function() {
EditHelpers.installEditTemplates();
runtime = new window.StudioRuntime.v1();
});
@@ -20,7 +21,7 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm
});
it('shows save notifications', function() {
var title = "Mock saving...",
var title = 'Mock saving...',
notificationSpy = EditHelpers.createNotificationSpy();
runtime.notify('save', {
state: 'start',
@@ -34,9 +35,9 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm
});
it('shows error messages', function() {
var title = "Mock Error",
message = "This is a mock error.",
notificationSpy = EditHelpers.createNotificationSpy("Error");
var title = 'Mock Error',
message = 'This is a mock error.',
notificationSpy = EditHelpers.createNotificationSpy('Error');
runtime.notify('error', {
title: title,
message: message
@@ -44,7 +45,7 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm
EditHelpers.verifyNotificationShowing(notificationSpy, title);
});
describe("Modal Dialogs", function() {
describe('Modal Dialogs', function() {
var MockModal, modal, showMockModal;
MockModal = BaseModal.extend({
@@ -55,12 +56,12 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm
showMockModal = function() {
modal = new MockModal({
title: "Mock Modal"
title: 'Mock Modal'
});
modal.show();
};
beforeEach(function () {
beforeEach(function() {
EditHelpers.installEditTemplates();
});
@@ -68,7 +69,7 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm
EditHelpers.hideModalIfShowing(modal);
});
it('cancels a modal dialog', function () {
it('cancels a modal dialog', function() {
showMockModal();
runtime.notify('modal-shown', modal);
expect(EditHelpers.isShowingModal(modal)).toBeTruthy();

View File

@@ -0,0 +1,188 @@
define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/modal',
'common/js/components/views/feedback_notification'],
function($, Backbone, XBlock, URI, gettext, ModalUtils, NotificationView) {
'use strict';
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) {
var key;
for (key in parent) {
if (__hasProp.call(parent, key)) {
child[key] = parent[key];
}
}
function Ctor() {
this.constructor = child;
}
Ctor.prototype = parent.prototype;
child.prototype = new Ctor();
child.__super__ = parent.prototype;
return child;
},
BaseRuntime = {},
PreviewRuntime = {},
StudioRuntime = {};
BaseRuntime.v1 = (function(_super) {
__extends(v1, _super);
v1.prototype.handlerUrl = function(element, handlerName, suffix, query) {
var uri;
uri = URI(this.handlerPrefix)
.segment($(element).data('usage-id'))
.segment('handler')
.segment(handlerName);
if (suffix !== null) {
uri.segment(suffix);
}
if (query !== null) {
uri.search(query);
}
return uri.toString();
};
function v1() {
v1.__super__.constructor.call(this);
this.dispatcher = _.clone(Backbone.Events);
this.listenTo('save', this._handleSave);
this.listenTo('cancel', this._handleCancel);
this.listenTo('error', this._handleError);
this.listenTo('modal-shown', function(data) {
this.modal = data;
});
this.listenTo('modal-hidden', function() {
this.modal = null;
});
this.listenTo('page-shown', function(data) {
this.page = data;
});
}
/**
* Notify the Studio client-side runtime of an event so that it
* can update the UI in a consistent way.
*
* @param {string} name The name of the event.
* @param {object} data A JSON representation of the data to be included with the event.
*/
v1.prototype.notify = function(name, data) {
this.dispatcher.trigger(name, data);
};
/**
* Listen to a Studio event and invoke the specified callback when it is triggered.
*
* @param {string} name The name of the event.
* @param {function} callback The callback to be invoked.
*/
v1.prototype.listenTo = function(name, callback) {
this.dispatcher.bind(name, callback, this);
};
/**
* Refresh the view for the xblock represented by the specified element.
*
* @param {element} element The element representing the XBlock.
*/
v1.prototype.refreshXBlock = function(element) {
if (this.page) {
this.page.refreshXBlock(element);
}
};
v1.prototype._handleError = function(data) {
var message, title;
message = data.message || data.msg;
if (message) {
// TODO: remove 'Open Assessment' specific default title
title = data.title || gettext('OpenAssessment Save Error');
this.alert = new NotificationView.Error({
title: title,
message: message,
closeIcon: false,
shown: false
});
this.alert.show();
}
};
v1.prototype._handleSave = function(data) {
var message;
// Starting to save, so show a notification
if (data.state === 'start') {
message = data.message || gettext('Saving');
this.notification = new NotificationView.Mini({
title: message
});
this.notification.show();
} else if (data.state === 'end') {
// Finished saving, so hide the notification and refresh appropriately
this._hideAlerts();
if (this.modal && this.modal.onSave) {
// Notify the modal that the save has completed so that it can hide itself
// and then refresh the xblock.
this.modal.onSave();
} else if (data.element) {
// ... else ask it to refresh the newly saved xblock
this.refreshXBlock(data.element);
}
this.notification.hide();
}
};
v1.prototype._handleCancel = function() {
this._hideAlerts();
if (this.modal) {
this.modal.cancel();
this.notify('modal-hidden');
}
};
/**
* Hide any alerts that are being shown.
*/
v1.prototype._hideAlerts = function() {
if (this.alert && this.alert.options.shown) {
this.alert.hide();
}
};
return v1;
})(XBlock.Runtime.v1);
PreviewRuntime.v1 = (function(_super) {
__extends(v1, _super);
function v1() {
return v1.__super__.constructor.apply(this, arguments);
}
v1.prototype.handlerPrefix = '/preview/xblock';
return v1;
})(BaseRuntime.v1);
StudioRuntime.v1 = (function(_super) {
__extends(v1, _super);
function v1() {
return v1.__super__.constructor.apply(this, arguments);
}
v1.prototype.handlerPrefix = '/xblock';
return v1;
})(BaseRuntime.v1);
// Install the runtime's into the global namespace
window.BaseRuntime = BaseRuntime;
window.PreviewRuntime = PreviewRuntime;
window.StudioRuntime = StudioRuntime;
});

View File

@@ -1,299 +0,0 @@
requirejs.config({
baseUrl: '/base/',
paths: {
"gettext": "xmodule_js/common_static/js/test/i18n",
"mustache": "xmodule_js/common_static/js/vendor/mustache",
"codemirror": "xmodule_js/common_static/js/vendor/CodeMirror/codemirror",
"jquery": "xmodule_js/common_static/common/js/vendor/jquery",
"jquery-migrate": "xmodule_js/common_static/common/js/vendor/jquery-migrate",
"jquery.ui": "xmodule_js/common_static/js/vendor/jquery-ui.min",
"jquery.form": "xmodule_js/common_static/js/vendor/jquery.form",
"jquery.markitup": "xmodule_js/common_static/js/vendor/markitup/jquery.markitup",
"jquery.leanModal": "xmodule_js/common_static/js/vendor/jquery.leanModal",
"jquery.ajaxQueue": "xmodule_js/common_static/js/vendor/jquery.ajaxQueue",
"jquery.smoothScroll": "xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min",
"jquery.scrollTo": "common/js/vendor/jquery.scrollTo",
"jquery.timepicker": "xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker",
"jquery.cookie": "xmodule_js/common_static/js/vendor/jquery.cookie",
"jquery.qtip": "xmodule_js/common_static/js/vendor/jquery.qtip.min",
"jquery.fileupload": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload",
"jquery.fileupload-process": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process",
"jquery.fileupload-validate": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate",
"jquery.iframe-transport": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport",
"jquery.inputnumber": "xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill",
"jquery.immediateDescendents": "xmodule_js/common_static/coffee/src/jquery.immediateDescendents",
"jquery.simulate": "xmodule_js/common_static/js/vendor/jquery.simulate",
"datepair": "xmodule_js/common_static/js/vendor/timepicker/datepair",
"date": "xmodule_js/common_static/js/vendor/date",
"moment": "xmodule_js/common_static/js/vendor/moment.min",
"moment-with-locales": "xmodule_js/common_static/js/vendor/moment-with-locales.min",
"text": "xmodule_js/common_static/js/vendor/requirejs/text",
"underscore": "common/js/vendor/underscore",
"underscore.string": "common/js/vendor/underscore.string",
"backbone": "common/js/vendor/backbone",
"backbone.associations": "xmodule_js/common_static/js/vendor/backbone-associations-min",
"backbone.paginator": "common/js/vendor/backbone.paginator",
"backbone-relational": "xmodule_js/common_static/js/vendor/backbone-relational.min",
"tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min",
"jquery.tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce",
"xmodule": "xmodule_js/src/xmodule",
"xblock/cms.runtime.v1": "coffee/src/xblock/cms.runtime.v1",
"xblock/core": "xmodule_js/common_static/js/xblock/core",
"xblock": "xmodule_js/common_static/coffee/src/xblock",
"utility": "xmodule_js/common_static/js/src/utility",
"accessibility": "xmodule_js/common_static/js/src/accessibility_tools",
"sinon": "xmodule_js/common_static/js/vendor/sinon-1.17.0",
"squire": "xmodule_js/common_static/js/vendor/Squire",
"jasmine-imagediff": "xmodule_js/common_static/js/vendor/jasmine-imagediff",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly",
"domReady": "xmodule_js/common_static/js/vendor/domReady",
"URI": "xmodule_js/common_static/js/vendor/URI.min",
"mock-ajax": "xmodule_js/common_static/js/vendor/mock-ajax",
"modernizr": "edx-pattern-library/js/modernizr-custom",
"afontgarde": "edx-pattern-library/js/afontgarde",
"edxicons": "edx-pattern-library/js/edx-icons",
"mathjax": "//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured",
"youtube": "//www.youtube.com/player_api?noext",
"coffee/src/ajax_prefix": "xmodule_js/common_static/coffee/src/ajax_prefix",
"js/spec/test_utils": "js/spec/test_utils",
}
shim: {
"gettext": {
exports: "gettext"
},
"date": {
exports: "Date"
},
"jquery-migrate": ['jquery'],
"jquery.ui": {
deps: ["jquery"],
exports: "jQuery.ui"
},
"jquery.form": {
deps: ["jquery"],
exports: "jQuery.fn.ajaxForm"
},
"jquery.markitup": {
deps: ["jquery"],
exports: "jQuery.fn.markitup"
},
"jquery.leanModal": {
deps: ["jquery"],
exports: "jQuery.fn.leanModal"
},
"jquery.smoothScroll": {
deps: ["jquery"],
exports: "jQuery.fn.smoothScroll"
},
"jquery.ajaxQueue": {
deps: ["jquery"],
exports: "jQuery.fn.ajaxQueue"
},
"jquery.scrollTo": {
deps: ["jquery"],
exports: "jQuery.fn.scrollTo"
},
"jquery.cookie": {
deps: ["jquery"],
exports: "jQuery.fn.cookie"
},
"jquery.qtip": {
deps: ["jquery"],
exports: "jQuery.fn.qtip"
},
"jquery.fileupload": {
deps: ["jquery.ui", "jquery.iframe-transport"],
exports: "jQuery.fn.fileupload"
},
"jquery.fileupload-process": {
deps: ["jquery.fileupload"]
},
"jquery.fileupload-validate": {
deps: ["jquery.fileupload"]
},
"jquery.inputnumber": {
deps: ["jquery"],
exports: "jQuery.fn.inputNumber"
},
"jquery.simulate": {
deps: ["jquery"],
exports: "jQuery.fn.simulate"
},
"jquery.tinymce": {
deps: ["jquery", "tinymce"],
exports: "jQuery.fn.tinymce"
},
"datepair": {
deps: ["jquery.ui", "jquery.timepicker"]
},
"underscore": {
exports: "_"
},
"backbone": {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
"backbone.associations": {
deps: ["backbone"],
exports: "Backbone.Associations"
},
"backbone.paginator": {
deps: ["backbone"],
exports: "Backbone.PageableCollection"
},
"backbone-relational": {
deps: ["backbone"],
},
"youtube": {
exports: "YT"
},
"codemirror": {
exports: "CodeMirror"
},
"tinymce": {
exports: "tinymce"
},
"mathjax": {
exports: "MathJax",
init: ->
MathJax.Hub.Config
tex2jax:
inlineMath: [
["\\(", "\\)"],
['[mathjaxinline]', '[/mathjaxinline]']
]
displayMath: [
["\\[", "\\]"],
['[mathjax]', '[/mathjax]']
]
MathJax.Hub.Configured()
},
"URI": {
exports: "URI"
},
"xmodule": {
exports: "XModule"
},
"sinon": {
exports: "sinon"
},
"jasmine-imagediff": {},
"common/js/spec_helpers/jasmine-extensions": {
deps: ["jquery"]
},
"common/js/spec_helpers/jasmine-stealth": {
deps: ["underscore", "underscore.string"]
},
"common/js/spec_helpers/jasmine-waituntil": {
deps: ["jquery"]
},
"xblock/core": {
exports: "XBlock",
deps: ["jquery", "jquery.immediateDescendents"]
},
"xblock/runtime.v1": {
exports: "XBlock",
deps: ["xblock/core"]
},
"mock-ajax": {
deps: ["jquery"]
}
"coffee/src/main": {
deps: ["coffee/src/ajax_prefix"]
},
"coffee/src/ajax_prefix": {
deps: ["jquery"]
},
"modernizr": {
exports: "Modernizr"
},
"afontgarde": {
exports: "AFontGarde"
}
}
});
jasmine.getFixtures().fixturesPath += 'coffee/fixtures'
testFiles = [
"coffee/spec/main_spec",
"coffee/spec/models/course_spec",
"coffee/spec/models/metadata_spec",
"coffee/spec/models/section_spec",
"coffee/spec/models/settings_course_grader_spec",
"coffee/spec/models/settings_grading_spec",
"coffee/spec/models/textbook_spec",
"coffee/spec/models/upload_spec",
"coffee/spec/views/course_info_spec",
"coffee/spec/views/metadata_edit_spec",
"coffee/spec/views/module_edit_spec",
"coffee/spec/views/textbook_spec",
"coffee/spec/views/upload_spec",
"js/spec/video/transcripts/utils_spec",
"js/spec/video/transcripts/editor_spec",
"js/spec/video/transcripts/videolist_spec",
"js/spec/video/transcripts/message_manager_spec",
"js/spec/video/transcripts/file_uploader_spec",
"js/spec/models/component_template_spec",
"js/spec/models/explicit_url_spec",
"js/spec/models/xblock_info_spec",
"js/spec/models/xblock_validation_spec",
"js/spec/models/license_spec",
"js/spec/utils/drag_and_drop_spec",
"js/spec/utils/handle_iframe_binding_spec",
"js/spec/utils/module_spec",
"js/spec/views/active_video_upload_list_spec",
"js/spec/views/previous_video_upload_spec",
"js/spec/views/previous_video_upload_list_spec",
"js/spec/views/assets_spec",
"js/spec/views/baseview_spec",
"js/spec/views/container_spec",
"js/spec/views/paged_container_spec",
"js/spec/views/group_configuration_spec",
"js/spec/views/unit_outline_spec",
"js/spec/views/xblock_spec",
"js/spec/views/xblock_editor_spec",
"js/spec/views/xblock_string_field_editor_spec",
"js/spec/views/xblock_validation_spec",
"js/spec/views/license_spec",
"js/spec/views/paging_spec",
"js/spec/views/login_studio_spec",
"js/spec/views/pages/container_spec",
"js/spec/views/pages/container_subviews_spec",
"js/spec/views/pages/group_configurations_spec",
"js/spec/views/pages/course_outline_spec",
"js/spec/views/pages/course_rerun_spec",
"js/spec/views/pages/index_spec",
"js/spec/views/pages/library_users_spec",
"js/spec/views/modals/base_modal_spec",
"js/spec/views/modals/edit_xblock_spec",
"js/spec/views/modals/validation_error_modal_spec",
"js/spec/views/settings/main_spec",
"js/spec/factories/xblock_validation_spec",
"js/spec/xblock/cms.runtime.v1_spec",
"js/certificates/spec/models/certificate_spec",
"js/certificates/spec/views/certificate_details_spec",
"js/certificates/spec/views/certificate_editor_spec",
"js/certificates/spec/views/certificates_list_spec",
"js/certificates/spec/views/certificate_preview_spec"
]
i = 0
while i < testFiles.length
testFiles[i] = '/base/' + testFiles[i] + '.js'
i++
specHelpers = [
'common/js/spec_helpers/jasmine-extensions',
'common/js/spec_helpers/jasmine-stealth',
'common/js/spec_helpers/jasmine-waituntil'
]
# Jasmine has a global stack for creating a tree of specs. We need to load
# spec files one by one, otherwise some end up getting nested under others.
requireSerial specHelpers.concat(testFiles), ->
# start test run, once Require.js is done
window.__karma__.start()

View File

@@ -1,218 +0,0 @@
requirejs.config({
baseUrl: '/base/',
paths: {
"gettext": "xmodule_js/common_static/js/test/i18n",
"mustache": "xmodule_js/common_static/js/vendor/mustache",
"codemirror": "xmodule_js/common_static/js/vendor/CodeMirror/codemirror",
"jquery": "common/js/vendor/jquery",
"jquery-migrate": "common/js/vendor/jquery-migrate",
"jquery.ui": "xmodule_js/common_static/js/vendor/jquery-ui.min",
"jquery.form": "xmodule_js/common_static/js/vendor/jquery.form",
"jquery.markitup": "xmodule_js/common_static/js/vendor/markitup/jquery.markitup",
"jquery.leanModal": "xmodule_js/common_static/js/vendor/jquery.leanModal",
"jquery.smoothScroll": "xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min",
"jquery.scrollTo": "common/js/vendor/jquery.scrollTo",
"jquery.timepicker": "xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker",
"jquery.cookie": "xmodule_js/common_static/js/vendor/jquery.cookie",
"jquery.qtip": "xmodule_js/common_static/js/vendor/jquery.qtip.min",
"jquery.fileupload": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload",
"jquery.fileupload-process": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process",
"jquery.fileupload-validate": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate",
"jquery.iframe-transport": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport",
"jquery.inputnumber": "xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill",
"jquery.immediateDescendents": "xmodule_js/common_static/coffee/src/jquery.immediateDescendents",
"datepair": "xmodule_js/common_static/js/vendor/timepicker/datepair",
"date": "xmodule_js/common_static/js/vendor/date",
"text": "xmodule_js/common_static/js/vendor/requirejs/text",
"underscore": "common/js/vendor/underscore",
"underscore.string": "common/js/vendor/underscore.string",
"backbone": "common/js/vendor/backbone",
"backbone.associations": "xmodule_js/common_static/js/vendor/backbone-associations-min",
"backbone.paginator": "common/js/vendor/backbone.paginator",
"tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min",
"jquery.tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce",
"xmodule": "xmodule_js/src/xmodule",
"xblock/cms.runtime.v1": "coffee/src/xblock/cms.runtime.v1",
"xblock/core": "xmodule_js/common_static/js/xblock/core",
"xblock": "xmodule_js/common_static/coffee/src/xblock",
"utility": "xmodule_js/common_static/js/src/utility",
"sinon": "xmodule_js/common_static/js/vendor/sinon-1.17.0",
"squire": "xmodule_js/common_static/js/vendor/Squire",
"modernizr": "edx-pattern-library/js/modernizr-custom",
"afontgarde": "edx-pattern-library/js/afontgarde",
"edxicons": "edx-pattern-library/js/edx-icons",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly",
"domReady": "xmodule_js/common_static/js/vendor/domReady",
"URI": "xmodule_js/common_static/js/vendor/URI.min",
"mathjax": "//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured",
"youtube": "//www.youtube.com/player_api?noext",
"coffee/src/ajax_prefix": "xmodule_js/common_static/coffee/src/ajax_prefix"
}
shim: {
"gettext": {
exports: "gettext"
},
"date": {
exports: "Date"
},
"jquery.ui": {
deps: ["jquery"],
exports: "jQuery.ui"
},
"jquery.form": {
deps: ["jquery"],
exports: "jQuery.fn.ajaxForm"
},
"jquery.markitup": {
deps: ["jquery"],
exports: "jQuery.fn.markitup"
},
"jquery.leanModal": {
deps: ["jquery"],
exports: "jQuery.fn.leanModal"
},
"jquery.smoothScroll": {
deps: ["jquery"],
exports: "jQuery.fn.smoothScroll"
},
"jquery.scrollTo": {
deps: ["jquery"],
exports: "jQuery.fn.scrollTo"
},
"jquery.cookie": {
deps: ["jquery"],
exports: "jQuery.fn.cookie"
},
"jquery.qtip": {
deps: ["jquery"],
exports: "jQuery.fn.qtip"
},
"jquery.fileupload": {
deps: ["jquery.ui", "jquery.iframe-transport"],
exports: "jQuery.fn.fileupload"
},
"jquery.fileupload-process": {
deps: ["jquery.fileupload"]
},
"jquery.fileupload-validate": {
deps: ["jquery.fileupload"]
},
"jquery.inputnumber": {
deps: ["jquery"],
exports: "jQuery.fn.inputNumber"
},
"jquery.tinymce": {
deps: ["jquery", "tinymce"],
exports: "jQuery.fn.tinymce"
},
"datepair": {
deps: ["jquery.ui", "jquery.timepicker"]
},
"underscore": {
exports: "_"
},
"backbone": {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
"backbone.associations": {
deps: ["backbone"],
exports: "Backbone.Associations"
},
"backbone.paginator": {
deps: ["backbone"],
exports: "Backbone.PageableCollection"
},
"youtube": {
exports: "YT"
},
"codemirror": {
exports: "CodeMirror"
},
"tinymce": {
exports: "tinymce"
},
"mathjax": {
exports: "MathJax",
init: ->
MathJax.Hub.Config
tex2jax:
inlineMath: [
["\\(","\\)"],
['[mathjaxinline]','[/mathjaxinline]']
]
displayMath: [
["\\[","\\]"],
['[mathjax]','[/mathjax]']
]
MathJax.Hub.Configured();
},
"URI": {
exports: "URI"
},
"xmodule": {
exports: "XModule"
},
"sinon": {
exports: "sinon"
},
"common/js/spec_helpers/jasmine-extensions": {
deps: ["jquery"]
},
"common/js/spec_helpers/jasmine-stealth": {
deps: ["underscore", "underscore.string"]
},
"common/js/spec_helpers/jasmine-waituntil": {
deps: ["jquery"]
},
"xblock/core": {
exports: "XBlock",
deps: ["jquery", "jquery.immediateDescendents"]
},
"xblock/runtime.v1": {
exports: "XBlock",
deps: ["xblock/core"]
},
"coffee/src/main": {
deps: ["coffee/src/ajax_prefix"]
},
"coffee/src/ajax_prefix": {
deps: ["jquery"]
},
"modernizr": {
exports: "Modernizr"
},
"afontgarde": {
exports: "AFontGarde"
}
}
});
jasmine.getFixtures().fixturesPath += 'coffee/fixtures'
testFiles = [
'coffee/spec/views/assets_spec',
'js/spec/video/translations_editor_spec',
'js/spec/video/file_uploader_editor_spec',
'js/spec/models/group_configuration_spec'
]
i = 0
while i < testFiles.length
testFiles[i] = '/base/' + testFiles[i] + '.js'
i++
specHelpers = [
'common/js/spec_helpers/jasmine-extensions',
'common/js/spec_helpers/jasmine-stealth',
'common/js/spec_helpers/jasmine-waituntil'
]
# Jasmine has a global stack for creating a tree of specs. We need to load
# spec files one by one, otherwise some end up getting nested under others.
requireSerial specHelpers.concat(testFiles), ->
# start test run, once Require.js is done
window.__karma__.start()

View File

@@ -1,96 +0,0 @@
define [
"jquery", "backbone", "xblock/runtime.v1", "URI", "gettext",
"js/utils/modal", "common/js/components/views/feedback_notification"
], ($, Backbone, XBlock, URI, gettext, ModalUtils, NotificationView) ->
@BaseRuntime = {}
class BaseRuntime.v1 extends XBlock.Runtime.v1
handlerUrl: (element, handlerName, suffix, query, thirdparty) ->
uri = URI(@handlerPrefix).segment($(element).data('usage-id'))
.segment('handler')
.segment(handlerName)
if suffix? then uri.segment(suffix)
if query? then uri.search(query)
uri.toString()
constructor: () ->
super()
@dispatcher = _.clone(Backbone.Events)
@listenTo('save', @_handleSave)
@listenTo('cancel', @_handleCancel)
@listenTo('error', @_handleError)
@listenTo('modal-shown', (data) ->
@modal = data)
@listenTo('modal-hidden', () ->
@modal = null)
@listenTo('page-shown', (data) ->
@page = data)
# Notify the Studio client-side runtime of an event so that it can update the UI in a consistent way.
notify: (name, data) ->
@dispatcher.trigger(name, data)
# Listen to a Studio event and invoke the specified callback when it is triggered.
listenTo: (name, callback) ->
@dispatcher.bind(name, callback, this)
# Refresh the view for the xblock represented by the specified element.
refreshXBlock: (element) ->
if @page
@page.refreshXBlock(element)
_handleError: (data) ->
message = data.message || data.msg
if message
# TODO: remove 'Open Assessment' specific default title
title = data.title || gettext("OpenAssessment Save Error")
@alert = new NotificationView.Error
title: title
message: message
closeIcon: false
shown: false
@alert.show()
_handleSave: (data) ->
# Starting to save, so show a notification
if data.state == 'start'
message = data.message || gettext('Saving')
@notification = new NotificationView.Mini
title: message
@notification.show()
# Finished saving, so hide the notification and refresh appropriately
else if data.state == 'end'
@_hideAlerts()
# Notify the modal that the save has completed so that it can hide itself
# and then refresh the xblock.
if @modal and @modal.onSave
@modal.onSave()
# ... else ask it to refresh the newly saved xblock
else if data.element
@refreshXBlock(data.element)
@notification.hide()
_handleCancel: () ->
@_hideAlerts()
if @modal
@modal.cancel()
@notify('modal-hidden')
_hideAlerts: () ->
# Hide any alerts that are being shown
if @alert && @alert.options.shown
@alert.hide()
@PreviewRuntime = {}
class PreviewRuntime.v1 extends BaseRuntime.v1
handlerPrefix: '/preview/xblock'
@StudioRuntime = {}
class StudioRuntime.v1 extends BaseRuntime.v1
handlerPrefix: '/xblock'

View File

@@ -21,11 +21,13 @@ var options = {
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
sourceFiles: [
{pattern: 'cms/**/!(*spec|djangojs).js'},
{pattern: 'coffee/src/**/!(*spec).js'},
{pattern: 'js/**/!(*spec|djangojs).js'}
],
specFiles: [
{pattern: 'cms/**/*spec.js'},
{pattern: 'coffee/spec/**/*spec.js'},
{pattern: 'js/certificates/spec/**/*spec.js'},
{pattern: 'js/spec/**/*spec.js'}
@@ -37,10 +39,10 @@ var options = {
],
runFiles: [
{pattern: 'coffee/spec/main.js', included: true}
{pattern: 'cms/js/spec/main.js', included: true}
]
};
module.exports = function (config) {
module.exports = function(config) {
configModule.configure(config, options);
};

View File

@@ -36,7 +36,7 @@ var options = {
],
runFiles: [
{pattern: 'coffee/spec/main_squire.js', included: true}
{pattern: 'cms/js/spec/main_squire.js', included: true}
]
};

View File

@@ -23,6 +23,7 @@ class Command(BaseCommand):
parser.add_argument('--remove', dest='is_remove', action='store_true')
parser.add_argument('--superuser', dest='is_superuser', action='store_true')
parser.add_argument('--staff', dest='is_staff', action='store_true')
parser.add_argument('--unusable-password', dest='unusable_password', action='store_true')
parser.add_argument('-g', '--groups', nargs='*', default=[])
def _maybe_update(self, user, attribute, new_value):
@@ -68,7 +69,7 @@ class Command(BaseCommand):
user.delete()
@transaction.atomic
def handle(self, username, email, is_remove, is_staff, is_superuser, groups, *args, **options):
def handle(self, username, email, is_remove, is_staff, is_superuser, groups, unusable_password, *args, **options):
if is_remove:
return self._handle_remove(username, email)
@@ -91,6 +92,11 @@ class Command(BaseCommand):
self._maybe_update(user, 'is_staff', is_staff)
self._maybe_update(user, 'is_superuser', is_superuser)
# Set unusable password if specified
if unusable_password and user.has_usable_password():
self.stderr.write(_('Setting unusable password for user "{}"').format(user))
user.set_unusable_password()
# Ensure the user has a profile
try:
__ = user.profile

View File

@@ -48,6 +48,29 @@ class TestManageUserCommand(TestCase):
call_command('manage_user', TEST_USERNAME, TEST_EMAIL, '--remove')
self.assertEqual([], list(User.objects.all()))
def test_unusable_password(self):
"""
Ensure that a user's password is set to an unusable_password.
"""
user = User.objects.create(username=TEST_USERNAME, email=TEST_EMAIL)
self.assertEqual([(TEST_USERNAME, TEST_EMAIL)], [(u.username, u.email) for u in User.objects.all()])
user.set_password(User.objects.make_random_password())
user.save()
# Run once without passing --unusable-password and make sure the password is usable
call_command('manage_user', TEST_USERNAME, TEST_EMAIL)
user = User.objects.get(username=TEST_USERNAME, email=TEST_EMAIL)
self.assertTrue(user.has_usable_password())
# Make sure the user now has an unusable_password
call_command('manage_user', TEST_USERNAME, TEST_EMAIL, '--unusable-password')
user = User.objects.get(username=TEST_USERNAME, email=TEST_EMAIL)
self.assertFalse(user.has_usable_password())
# check idempotency
call_command('manage_user', TEST_USERNAME, TEST_EMAIL, '--unusable-password')
self.assertFalse(user.has_usable_password())
def test_wrong_email(self):
"""
Ensure that the operation is aborted if the username matches an

View File

@@ -1,96 +0,0 @@
describe "XBlock", ->
beforeEach ->
setFixtures """
<div>
<div class='xblock'
id='vA'
data-runtime-version="A"
data-runtime-class="TestRuntime"
data-init="initFnA"
data-name="a-name"
/>
<div>
<div class='xblock'
id='vZ'
data-runtime-version="Z"
data-runtime-class="TestRuntime"
data-init="initFnZ"
data-request-token="req-token-z"
/>
</div>
<div class='xblock' id='missing-version' data-init='initFnA' data-name='no-version'/>
<div class='xblock' id='missing-init' data-runtime-version="A" data-name='no-init'/>
</div>
"""
describe "initializeBlock", ->
beforeEach ->
window.TestRuntime = {}
@runtimeA = {name: 'runtimeA'}
@runtimeZ = {name: 'runtimeZ'}
TestRuntime.vA = jasmine.createSpy().and.returnValue(@runtimeA)
TestRuntime.vZ = jasmine.createSpy().and.returnValue(@runtimeZ)
window.initFnA = jasmine.createSpy()
window.initFnZ = jasmine.createSpy()
@fakeChildren = ['list', 'of', 'children']
spyOn(XBlock, 'initializeXBlocks').and.returnValue(@fakeChildren)
@vANode = $('#vA')[0]
@vZNode = $('#vZ')[0]
@vABlock = XBlock.initializeBlock(@vANode, 'req-token-a')
@vZBlock = XBlock.initializeBlock(@vZNode)
@missingVersionBlock = XBlock.initializeBlock($('#missing-version')[0])
@missingInitBlock = XBlock.initializeBlock($('#missing-init')[0])
it "loads the right runtime version", ->
expect(TestRuntime.vA).toHaveBeenCalledWith()
expect(TestRuntime.vZ).toHaveBeenCalledWith()
it "loads the right init function", ->
expect(window.initFnA).toHaveBeenCalledWith(@runtimeA, @vANode, {})
expect(window.initFnZ).toHaveBeenCalledWith(@runtimeZ, @vZNode, {})
it "loads when missing versions", ->
expect(@missingVersionBlock.element).toBe($('#missing-version')[0])
expect(@missingVersionBlock.name).toBe('no-version')
it "loads when missing init fn", ->
expect(@missingInitBlock.element).toBe($('#missing-init')[0])
expect(@missingInitBlock.name).toBe('no-init')
it "adds names to blocks", ->
expect(@vABlock.name).toBe('a-name')
it "leaves leaves missing names undefined", ->
expect(@vZBlock.name).toBeUndefined()
it "attaches the element to the block", ->
expect(@vABlock.element).toBe(@vANode)
expect(@vZBlock.element).toBe(@vZNode)
expect(@missingVersionBlock.element).toBe($('#missing-version')[0])
expect(@missingInitBlock.element).toBe($('#missing-init')[0])
it "passes through the request token", ->
expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(@vANode), 'req-token-a')
expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(@vZNode), 'req-token-z')
describe "initializeBlocks", ->
beforeEach ->
spyOn(XBlock, 'initializeBlock')
@vANode = $('#vA')[0]
@vZNode = $('#vZ')[0]
it "initializes children", ->
XBlock.initializeBlocks($('#jasmine-fixtures'))
expect(XBlock.initializeBlock).toHaveBeenCalledWith(@vANode, undefined)
expect(XBlock.initializeBlock).toHaveBeenCalledWith(@vZNode, undefined)
it "only initializes matching request tokens", ->
XBlock.initializeBlocks($('#jasmine-fixtures'), 'req-token-z')
expect(XBlock.initializeBlock).not.toHaveBeenCalledWith(@vANode, jasmine.any(Object))
expect(XBlock.initializeBlock).toHaveBeenCalledWith(@vZNode, 'req-token-z')

View File

@@ -1,21 +0,0 @@
describe "XBlock.Runtime.v1", ->
beforeEach ->
setFixtures """
<div class='xblock' data-handler-prefix='/xblock/fake-usage-id/handler'/>
"""
@children = [
{name: 'childA'},
{name: 'childB'}
]
@element = $('.xblock')[0]
$(@element).prop('xblock_children', @children)
@runtime = new XBlock.Runtime.v1(@element)
it "provides a list of children", ->
expect(@runtime.children(@element)).toBe(@children)
it "maps children by name", ->
expect(@runtime.childMap(@element, 'childA')).toBe(@children[0])
expect(@runtime.childMap(@element, 'childB')).toBe(@children[1])

View File

@@ -1,14 +0,0 @@
class XBlock.Runtime.v1
children: (block) => $(block).prop('xblock_children')
childMap: (block, childName) =>
for child in @children(block)
return child if child.name == childName
# Notify the client-side runtime that an event has occurred.
# This allows the runtime to update the UI in a consistent way
# for different XBlocks.
# `name` is an arbitrary string (for example, "save")
# `data` is an object (for example, {state: 'starting'})
# The default implementation is a no-op.
# WARNING: This is an interim solution and not officially supported!
notify: (name, data) -> undefined

View File

@@ -54,8 +54,7 @@ var commonFiles = {
],
sourceFiles: [
{pattern: 'common/js/components/**/*.js'},
{pattern: 'common/js/utils/**/*.js'}
{pattern: 'common/js/!(spec_helpers)/**/!(*spec).js'}
],
specFiles: [
@@ -173,7 +172,7 @@ var defaultNormalizeFunc = function (appRoot, pattern) {
pattern = path.join(appRoot, '/common/static/' + pattern);
} else if (pattern.match(/^xmodule_js\/common_static/)) {
pattern = path.join(appRoot, '/common/static/' +
pattern.replace(/^xmodule_js\/common_static\//, ''));
pattern.replace(/^xmodule_js\/common_static\//, ''));
}
return pattern;
};
@@ -184,7 +183,7 @@ var normalizePathsForCoverage = function(files, normalizeFunc) {
files.forEach(function (file) {
if (!file.ignoreCoverage) {
filesForCoverage[normalizeFn(appRoot, file.pattern)] = ['coverage'];
filesForCoverage[normalizeFn(appRoot, file.pattern)] = ['coverage'];
}
});
@@ -326,8 +325,18 @@ var getBaseConfig = function (config, useRequireJs) {
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Firefox'],
browsers: ['FirefoxNoUpdates'],
customLaunchers: {
// Firefox configuration that doesn't perform auto-updates
FirefoxNoUpdates: {
base: 'Firefox',
prefs: {
'app.update.auto': false,
'app.update.enabled': false
}
}
},
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
@@ -367,7 +376,7 @@ var configure = function(config, options) {
);
if (useRequireJs) {
files.unshift({pattern: 'common/js/utils/require-serial.js', included: true});
files.unshift({pattern: 'common/js/utils/require-serial.js', included: true});
}
// Karma sets included=true by default.
@@ -389,9 +398,9 @@ var configure = function(config, options) {
// If we give symlink paths to Istanbul, coverage for each path gets tracked
// separately. So we pass absolute paths to the karma-coverage preprocessor.
var preprocessors = _.extend(
{},
options.preprocessors,
normalizePathsForCoverage(filesForCoverage, options.normalizePathsForCoverageFunc)
{},
options.preprocessors,
normalizePathsForCoverage(filesForCoverage, options.normalizePathsForCoverageFunc)
);
config.set(_.extend(baseConfig, {

View File

@@ -0,0 +1,111 @@
(function() {
'use strict';
describe('XBlock', function() {
beforeEach(function() {
return setFixtures(
'<div>\n' +
' <div class="xblock"\n' +
' id="vA"\n' +
' data-runtime-version="A"\n' +
' data-runtime-class="TestRuntime"\n' +
' data-init="initFnA"\n' +
' data-name="a-name"\n' +
' />\n' +
' <div>\n' +
' <div class="xblock"\n' +
' id="vZ"\n' +
' data-runtime-version="Z"\n' +
' data-runtime-class="TestRuntime"\n' +
' data-init="initFnZ"\n' +
' data-request-token="req-token-z"\n' +
' />\n' +
' </div>\n' +
' <div class="xblock" id="missing-version" data-init="initFnA" data-name="no-version"/>\n' +
' <div class="xblock" id="missing-init" data-runtime-version="A" data-name="no-init"/>\n' +
'</div>');
});
describe('initializeBlock', function() {
beforeEach(function() {
window.TestRuntime = {};
this.runtimeA = {
name: 'runtimeA'
};
this.runtimeZ = {
name: 'runtimeZ'
};
window.TestRuntime.vA = jasmine.createSpy().and.returnValue(this.runtimeA);
window.TestRuntime.vZ = jasmine.createSpy().and.returnValue(this.runtimeZ);
window.initFnA = jasmine.createSpy();
window.initFnZ = jasmine.createSpy();
this.fakeChildren = ['list', 'of', 'children'];
spyOn(XBlock, 'initializeXBlocks').and.returnValue(this.fakeChildren);
this.vANode = $('#vA')[0];
this.vZNode = $('#vZ')[0];
this.vABlock = XBlock.initializeBlock(this.vANode, 'req-token-a');
this.vZBlock = XBlock.initializeBlock(this.vZNode);
this.missingVersionBlock = XBlock.initializeBlock($('#missing-version')[0]);
this.missingInitBlock = XBlock.initializeBlock($('#missing-init')[0]);
});
it('loads the right runtime version', function() {
expect(window.TestRuntime.vA).toHaveBeenCalledWith();
expect(window.TestRuntime.vZ).toHaveBeenCalledWith();
});
it('loads the right init function', function() {
expect(window.initFnA).toHaveBeenCalledWith(this.runtimeA, this.vANode, {});
expect(window.initFnZ).toHaveBeenCalledWith(this.runtimeZ, this.vZNode, {});
});
it('loads when missing versions', function() {
expect(this.missingVersionBlock.element).toBe($('#missing-version')[0]);
expect(this.missingVersionBlock.name).toBe('no-version');
});
it('loads when missing init fn', function() {
expect(this.missingInitBlock.element).toBe($('#missing-init')[0]);
expect(this.missingInitBlock.name).toBe('no-init');
});
it('adds names to blocks', function() {
expect(this.vABlock.name).toBe('a-name');
});
it('leaves leaves missing names undefined', function() {
expect(this.vZBlock.name).toBeUndefined();
});
it('attaches the element to the block', function() {
expect(this.vABlock.element).toBe(this.vANode);
expect(this.vZBlock.element).toBe(this.vZNode);
expect(this.missingVersionBlock.element).toBe($('#missing-version')[0]);
expect(this.missingInitBlock.element).toBe($('#missing-init')[0]);
});
it('passes through the request token', function() {
expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(this.vANode), 'req-token-a');
expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(this.vZNode), 'req-token-z');
});
});
describe('initializeBlocks', function() {
beforeEach(function() {
spyOn(XBlock, 'initializeBlock');
this.vANode = $('#vA')[0];
this.vZNode = $('#vZ')[0];
});
it('initializes children', function() {
XBlock.initializeBlocks($('#jasmine-fixtures'));
expect(XBlock.initializeBlock).toHaveBeenCalledWith(this.vANode, void 0);
expect(XBlock.initializeBlock).toHaveBeenCalledWith(this.vZNode, void 0);
});
it('only initializes matching request tokens', function() {
XBlock.initializeBlocks($('#jasmine-fixtures'), 'req-token-z');
expect(XBlock.initializeBlock).not.toHaveBeenCalledWith(this.vANode, jasmine.any(Object));
expect(XBlock.initializeBlock).toHaveBeenCalledWith(this.vZNode, 'req-token-z');
});
});
});
}).call(this);

View File

@@ -0,0 +1,28 @@
(function() {
'use strict';
describe('XBlock.Runtime.v1', function() {
beforeEach(function() {
setFixtures('<div class="xblock" data-handler-prefix="/xblock/fake-usage-id/handler"/>');
this.children = [
{
name: 'childA'
}, {
name: 'childB'
}
];
this.element = $('.xblock')[0];
$(this.element).prop('xblock_children', this.children);
this.runtime = new XBlock.Runtime.v1(this.element);
});
it('provides a list of children', function() {
expect(this.runtime.children(this.element)).toBe(this.children);
});
it('maps children by name', function() {
expect(this.runtime.childMap(this.element, 'childA')).toBe(this.children[0]);
expect(this.runtime.childMap(this.element, 'childB')).toBe(this.children[1]);
});
});
}).call(this);

View File

@@ -1,13 +1,15 @@
(function($, JSON) {
'use strict';
function initializeBlockLikes(block_class, initializer, element, requestToken) {
var requestToken = requestToken || $(element).data('request-token');
var XBlock;
function initializeBlockLikes(blockClass, initializer, element, requestToken) {
var selector;
requestToken = requestToken || $(element).data('request-token');
if (requestToken) {
var selector = '.' + block_class + '[data-request-token="' + requestToken + '"]';
selector = '.' + blockClass + '[data-request-token="' + requestToken + '"]';
} else {
var selector = '.' + block_class;
selector = '.' + blockClass;
}
return $(element).immediateDescendents(selector).map(function(idx, elem) {
return initializer(elem, requestToken);
@@ -15,17 +17,19 @@
}
function elementRuntime(element) {
var $element = $(element);
var runtime = $element.data('runtime-class');
var version = $element.data('runtime-version');
var initFnName = $element.data('init');
var $element = $(element),
runtime = $element.data('runtime-class'),
version = $element.data('runtime-version'),
initFnName = $element.data('init');
if (runtime && version && initFnName) {
return new window[runtime]['v' + version];
return new window[runtime]['v' + version]();
} else {
if (runtime || version || initFnName) {
var elementTag = $('<div>').append($element.clone()).html();
console.log('Block ' + elementTag + ' is missing data-runtime, data-runtime-version or data-init, and can\'t be initialized');
console.log(
'Block ' + $element.outerHTML + ' is missing data-runtime, data-runtime-version or data-init, ' +
'and can\'t be initialized'
);
} // else this XBlock doesn't have a JS init function.
return null;
}
@@ -42,14 +46,13 @@
* The constructor is called with the arguments 'runtime', 'element',
* and then all of 'block_args'.
*/
function constructBlock(element, block_args) {
function constructBlock(element, blockArgs) {
var block;
var $element = $(element);
var runtime = elementRuntime(element);
block_args.unshift(element);
block_args.unshift(runtime);
blockArgs.unshift(element);
blockArgs.unshift(runtime);
if (runtime) {
@@ -59,7 +62,7 @@
// This create a new constructor that can then apply() the block_args
// to the initFn.
function Block() {
return initFn.apply(this, block_args);
return initFn.apply(this, blockArgs);
}
Block.prototype = initFn.prototype;
@@ -78,7 +81,7 @@
return block;
}
var XBlock = {
XBlock = {
Runtime: {},
/**
@@ -88,11 +91,12 @@
* the children themselves.
*/
initializeBlock: function(element, requestToken) {
var $element = $(element);
var $element = $(element),
children, asides;
var requestToken = requestToken || $element.data('request-token');
var children = XBlock.initializeXBlocks($element, requestToken);
var asides = XBlock.initializeXBlockAsides($element, requestToken);
requestToken = requestToken || $element.data('request-token');
children = XBlock.initializeXBlocks($element, requestToken);
asides = XBlock.initializeXBlockAsides($element, requestToken);
if (asides) {
children = children.concat(asides);
}
@@ -106,7 +110,7 @@
* If requestToken is omitted, use the data-request-token attribute from element, or use
* the request-tokens specified on the children themselves.
*/
initializeAside: function(element, requestToken) {
initializeAside: function(element) {
var blockUsageId = $(element).data('block-id');
var blockElement = $(element).siblings('[data-usage-id="' + blockUsageId + '"]')[0];
return constructBlock(element, [blockElement, initArgs(element)]);

View File

@@ -0,0 +1,50 @@
(function() {
'use strict';
XBlock.Runtime.v1 = (function() {
function v1() {
var _this = this;
this.childMap = function() {
return v1.prototype.childMap.apply(_this, arguments);
};
this.children = function() {
return v1.prototype.children.apply(_this, arguments);
};
}
v1.prototype.children = function(block) {
return $(block).prop('xblock_children');
};
v1.prototype.childMap = function(block, childName) {
var child, _i, _len, _ref;
_ref = this.children(block);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
if (child.name === childName) {
return child;
}
}
};
/**
* Notify the client-side runtime that an event has occurred.
*
* This allows the runtime to update the UI in a consistent way
* for different XBlocks.
* `name` is an arbitrary string (for example, "save")
* `data` is an object (for example, {state: 'starting'})
* The default implementation is a no-op.
*
* WARNING: This is an interim solution and not officially supported!
*/
v1.prototype.notify = function() {
// Do nothing
};
return v1;
})();
}).call(this);

View File

@@ -11,7 +11,7 @@ var options = {
useRequireJs: false,
normalizePathsForCoverageFunc: function (appRoot, pattern) {
normalizePathsForCoverageFunc: function(appRoot, pattern) {
return path.join(appRoot, '/common/static/' + pattern);
},
@@ -50,16 +50,17 @@ var options = {
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
sourceFiles: [
{pattern: 'js/xblock/**/*.js', included: true},
{pattern: 'coffee/src/**/*.js', included: true},
{pattern: 'js/src/**/*.js', included: true},
{pattern: 'js/capa/src/**/*.js', included: true}
{pattern: 'common/js/xblock/core.js', included: true},
{pattern: 'common/js/xblock/runtime.v1.js', included: true},
{pattern: 'js/capa/src/**/*.js', included: true},
{pattern: 'js/src/**/*.js', included: true}
],
specFiles: [
{pattern: 'coffee/spec/**/*.js', included: true},
{pattern: 'js/spec/**/*.js', included: true},
{pattern: 'js/capa/spec/**/*.js', included: true}
{pattern: 'common/js/spec/xblock/*.js', included: true},
{pattern: 'js/**/*spec.js', included: true}
],
fixtureFiles: [
@@ -69,6 +70,6 @@ var options = {
]
};
module.exports = function (config) {
module.exports = function(config) {
configModule.configure(config, options);
};

View File

@@ -8817,3 +8817,19 @@ msgstr ""
#: cms/templates/js/video/transcripts/messages/transcripts-use-existing.underscore
msgid "Use Current Transcript"
msgstr ""
#: lms/templates/verify_student/make_payment_step.underscore:47
msgid ""
"We ask you to activate your account to ensure it is really you creating the "
"account and to prevent fraud."
msgstr ""
#: lms/templates/verify_student/make_payment_step.underscore:41
msgid ""
"An email has been sent to {userEmail} with a link for you to activate your "
"account."
msgstr ""
#: lms/templates/verify_student/make_payment_step.underscore:45
msgid "Why activate?"
msgstr ""

View File

@@ -208,10 +208,16 @@ To run a single test format the command like this.
paver test_system -t lms/djangoapps/courseware/tests/tests.py:ActivateLoginTest.test_activate_login
The ``lms`` suite of tests runs concurrently, and with randomized order, by default.
You can override these by using ``--no-randomize`` to disable randomization,
and ``--processes=N`` to control how many tests will run concurrently (``0`` will
disable concurrency). For example:
The ``lms`` suite of tests runs with randomized order, by default.
You can override these by using ``--no-randomize`` to disable randomization.
You can also enable test concurrency with the ``--processes=N`` flag (where ``N``
is the number of processes to run tests with, and ``-1`` means one process per
available core). Note, however, that when running concurrently, breakpoints may
not work correctly, and you will not be able to run single test methods (only
single test classes).
For example:
::
# This will run all tests in the order that they appear in their files, serially

View File

@@ -418,6 +418,7 @@ class PayAndVerifyView(View):
'disable_courseware_js': True,
'display_steps': display_steps,
'is_active': json.dumps(request.user.is_active),
'user_email': request.user.email,
'message_key': message,
'platform_name': theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
'processors': processors,

View File

@@ -1528,9 +1528,14 @@ PIPELINE_CSS = {
}
common_js = set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.js')) - set(courseware_js + discussion_js + notes_js + instructor_dash_js) # pylint: disable=line-too-long
project_js = set(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.js')) - set(courseware_js + discussion_js + notes_js + instructor_dash_js) # pylint: disable=line-too-long
separately_bundled_js = set(courseware_js + discussion_js + notes_js + instructor_dash_js)
common_js = sorted(set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.js')) - separately_bundled_js)
xblock_runtime_js = [
'common/js/xblock/core.js',
'common/js/xblock/runtime.v1.js',
'lms/js/xblock/lms.runtime.v1.js',
]
lms_application_js = sorted(set(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.js')) - separately_bundled_js)
PIPELINE_JS = {
'base_application': {
@@ -1539,13 +1544,14 @@ PIPELINE_JS = {
},
'application': {
# Application will contain all paths not in courseware_only_js
'source_filenames': ['js/xblock/core.js'] + sorted(common_js) + sorted(project_js) + base_application_js + [
'js/sticky_filter.js',
'js/query-params.js',
'js/vendor/moment.min.js',
],
'source_filenames': (
common_js + xblock_runtime_js + base_application_js + lms_application_js +
[
'js/sticky_filter.js',
'js/query-params.js',
'js/vendor/moment.min.js',
]
),
'output_filename': 'js/lms-application.js',
},
'proctoring': {

View File

@@ -1,18 +0,0 @@
@LmsRuntime = {}
class LmsRuntime.v1 extends XBlock.Runtime.v1
handlerUrl: (element, handlerName, suffix, query, thirdparty) ->
courseId = $(element).data("course-id")
usageId = $(element).data("usage-id")
handlerAuth = if thirdparty then "handler_noauth" else "handler"
uri = URI('/courses').segment(courseId)
.segment('xblock')
.segment(usageId)
.segment(handlerAuth)
.segment(handlerName)
if suffix? then uri.segment(suffix)
if query? then uri.search(query)
uri.toString()

View File

@@ -142,6 +142,11 @@ define([
expectPaymentSubmitted( view, {foo: 'bar'} );
});
it ('view containing user email', function() {
createView({userEmail: 'test@example.com', requirements: {isVisible:true}, isActive: false});
expect($('p.instruction-info:contains("test@example.com")').length).toEqual(1);
});
it( 'provides working payment buttons for a single processor', function() {
createView({processors: ['cybersource']});
checkPaymentButtons( AjaxHelpers.requests(this), {cybersource: "Checkout"});

View File

@@ -49,6 +49,7 @@ var edx = edx || {};
requirements: el.data('requirements'),
courseKey: el.data('course-key'),
courseName: el.data('course-name'),
userEmail: el.data('user-email'),
hasVisibleReqs: _.some(
el.data('requirements'),
function( isVisible ) { return isVisible; }

View File

@@ -37,7 +37,8 @@ var edx = edx || {};
alreadyVerified: false,
courseModeSlug: 'audit',
verificationGoodUntil: '',
isABTesting: false
isABTesting: false,
userEmail: ''
};
},

View File

@@ -29,6 +29,7 @@ var options = {
{pattern: 'common/js/vendor/jquery.js', included: true},
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
{pattern: 'common/js/vendor/underscore.js', included: true},
{pattern: 'common/js/xblock/*.js', included: true},
{pattern: 'xmodule_js/common_static/js/src/logger.js', included: true},
{pattern: 'xmodule_js/common_static/js/test/i18n.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js', included: true},
@@ -38,8 +39,6 @@ var options = {
{pattern: 'xmodule_js/common_static/js/vendor/jquery-ui.min.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/URI.min.js', included: true},
{pattern: 'xmodule_js/common_static/js/xblock/*.js', included: true},
{pattern: 'xmodule_js/common_static/coffee/src/xblock/*.js', included: true},
{pattern: 'xmodule_js/src/capa/*.js', included: true},
{pattern: 'xmodule_js/src/video/*.js', included: true},
{pattern: 'xmodule_js/src/xmodule.js', included: true},

View File

@@ -1,4 +1,5 @@
;(function (require, define) {
;(function(require, define) {
'use strict';
// We do not wish to bundle common libraries (that may also be used by non-RequireJS code on the page
// into the optimized files. Therefore load these libraries through script tags and explicitly define them.
@@ -24,207 +25,207 @@
}
}
else {
console.error("Expected library to be included on page, but not found on window object: " + name);
console.error('Expected library to be included on page, but not found on window object: ' + name);
}
};
defineDependency("jQuery", "jquery");
defineDependency("jQuery", "jquery-migrate");
defineDependency("_", "underscore");
defineDependency("s", "underscore.string");
// Underscore.string no longer installs itself directly on "_". For compatibility with existing
// code, add it to "_" with its previous name.
defineDependency('jQuery', 'jquery');
defineDependency('jQuery', 'jquery-migrate');
defineDependency('_', 'underscore');
defineDependency('s', 'underscore.string');
// Underscore.string no longer installs itself directly on '_'. For compatibility with existing
// code, add it to '_' with its previous name.
if (window._ && window.s) {
window._.str = window.s;
}
defineDependency("gettext", "gettext");
defineDependency("Logger", "logger");
defineDependency("URI", "URI");
defineDependency("Backbone", "backbone");
defineDependency("Modernizr", "modernizr");
defineDependency('gettext', 'gettext');
defineDependency('Logger', 'logger');
defineDependency('URI', 'URI');
defineDependency('Backbone', 'backbone');
defineDependency('Modernizr', 'modernizr');
// Add the UI Toolkit helper classes that have been installed in the "edx" namespace
defineDependency("edx.HtmlUtils", "edx-ui-toolkit/js/utils/html-utils");
defineDependency("edx.StringUtils", "edx-ui-toolkit/js/utils/string-utils");
// Add the UI Toolkit helper classes that have been installed in the 'edx' namespace
defineDependency('edx.HtmlUtils', 'edx-ui-toolkit/js/utils/html-utils');
defineDependency('edx.StringUtils', 'edx-ui-toolkit/js/utils/string-utils');
// utility.js adds two functions to the window object, but does not return anything
defineDependency("isExternal", "utility", true);
defineDependency('isExternal', 'utility', true);
}
require.config({
// NOTE: baseUrl has been previously set in lms/templates/main.html
waitSeconds: 60,
paths: {
"annotator_1.2.9": "js/vendor/edxnotes/annotator-full.min",
"date": "js/vendor/date",
"moment": "js/vendor/moment.min",
"moment-with-locales": "xmodule_js/common_static/js/vendor/moment-with-locales.min",
"text": "js/vendor/requirejs/text",
"logger": "js/src/logger",
"backbone": "common/js/vendor/backbone",
"backbone-super": "js/vendor/backbone-super",
"backbone.paginator": "common/js/vendor/backbone.paginator",
"underscore": "common/js/vendor/underscore",
"underscore.string": "common/js/vendor/underscore.string",
'annotator_1.2.9': 'js/vendor/edxnotes/annotator-full.min',
'date': 'js/vendor/date',
'moment': 'js/vendor/moment.min',
'moment-with-locales': 'xmodule_js/common_static/js/vendor/moment-with-locales.min',
'text': 'js/vendor/requirejs/text',
'logger': 'js/src/logger',
'backbone': 'common/js/vendor/backbone',
'backbone-super': 'js/vendor/backbone-super',
'backbone.paginator': 'common/js/vendor/backbone.paginator',
'underscore': 'common/js/vendor/underscore',
'underscore.string': 'common/js/vendor/underscore.string',
// The jquery-migrate library was added in upgrading from
// jQuery 1.7.x to 2.2.x. This config allows developers
// to depend on "jquery" which opaquely requires both
// to depend on 'jquery' which opaquely requires both
// libraries.
"jquery": "common/js/vendor/jquery",
"jquery-migrate": "common/js/vendor/jquery-migrate",
"jquery.scrollTo": "common/js/vendor/jquery.scrollTo",
"jquery.cookie": "js/vendor/jquery.cookie",
'jquery': 'common/js/vendor/jquery',
'jquery-migrate': 'common/js/vendor/jquery-migrate',
'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo',
'jquery.cookie': 'js/vendor/jquery.cookie',
'jquery.timeago': 'js/vendor/jquery.timeago',
"jquery.url": "js/vendor/url.min",
"jquery.ui": "js/vendor/jquery-ui.min",
"jquery.iframe-transport": "js/vendor/jQuery-File-Upload/js/jquery.iframe-transport",
"jquery.fileupload": "js/vendor/jQuery-File-Upload/js/jquery.fileupload",
"URI": "js/vendor/URI.min",
"string_utils": "js/src/string_utils",
"utility": "js/src/utility",
"modernizr": "edx-pattern-library/js/modernizr-custom",
"afontgarde": "edx-pattern-library/js/afontgarde",
"edxicons": "edx-pattern-library/js/edx-icons",
"draggabilly": "js/vendor/draggabilly",
'jquery.url': 'js/vendor/url.min',
'jquery.ui': 'js/vendor/jquery-ui.min',
'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
'jquery.fileupload': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload',
'URI': 'js/vendor/URI.min',
'string_utils': 'js/src/string_utils',
'utility': 'js/src/utility',
'modernizr': 'edx-pattern-library/js/modernizr-custom',
'afontgarde': 'edx-pattern-library/js/afontgarde',
'edxicons': 'edx-pattern-library/js/edx-icons',
'draggabilly': 'js/vendor/draggabilly',
// Files needed by OVA
"annotator": "js/vendor/ova/annotator-full",
"annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth",
"video.dev": "js/vendor/ova/video.dev",
"vjs.youtube": "js/vendor/ova/vjs.youtube",
"rangeslider": "js/vendor/ova/rangeslider",
"share-annotator": "js/vendor/ova/share-annotator",
"richText-annotator": "js/vendor/ova/richText-annotator",
"reply-annotator": "js/vendor/ova/reply-annotator",
"grouping-annotator": "js/vendor/ova/grouping-annotator",
"tags-annotator": "js/vendor/ova/tags-annotator",
"diacritic-annotator": "js/vendor/ova/diacritic-annotator",
"flagging-annotator": "js/vendor/ova/flagging-annotator",
"jquery-Watch": "js/vendor/ova/jquery-Watch",
"openseadragon": "js/vendor/ova/openseadragon",
"osda": "js/vendor/ova/OpenSeaDragonAnnotation",
"ova": "js/vendor/ova/ova",
"catch": "js/vendor/ova/catch/js/catch",
"handlebars": "js/vendor/ova/catch/js/handlebars-1.1.2",
"tinymce": "js/vendor/tinymce/js/tinymce/tinymce.full.min",
"jquery.tinymce": "js/vendor/tinymce/js/tinymce/jquery.tinymce.min",
"picturefill": "common/js/vendor/picturefill"
'annotator': 'js/vendor/ova/annotator-full',
'annotator-harvardx': 'js/vendor/ova/annotator-full-firebase-auth',
'video.dev': 'js/vendor/ova/video.dev',
'vjs.youtube': 'js/vendor/ova/vjs.youtube',
'rangeslider': 'js/vendor/ova/rangeslider',
'share-annotator': 'js/vendor/ova/share-annotator',
'richText-annotator': 'js/vendor/ova/richText-annotator',
'reply-annotator': 'js/vendor/ova/reply-annotator',
'grouping-annotator': 'js/vendor/ova/grouping-annotator',
'tags-annotator': 'js/vendor/ova/tags-annotator',
'diacritic-annotator': 'js/vendor/ova/diacritic-annotator',
'flagging-annotator': 'js/vendor/ova/flagging-annotator',
'jquery-Watch': 'js/vendor/ova/jquery-Watch',
'openseadragon': 'js/vendor/ova/openseadragon',
'osda': 'js/vendor/ova/OpenSeaDragonAnnotation',
'ova': 'js/vendor/ova/ova',
'catch': 'js/vendor/ova/catch/js/catch',
'handlebars': 'js/vendor/ova/catch/js/handlebars-1.1.2',
'tinymce': 'js/vendor/tinymce/js/tinymce/tinymce.full.min',
'jquery.tinymce': 'js/vendor/tinymce/js/tinymce/jquery.tinymce.min',
'picturefill': 'common/js/vendor/picturefill'
// end of files needed by OVA
},
shim: {
"annotator_1.2.9": {
deps: ["jquery"],
exports: "Annotator"
'annotator_1.2.9': {
deps: ['jquery'],
exports: 'Annotator'
},
"date": {
exports: "Date"
'date': {
exports: 'Date'
},
"jquery": {
exports: "jQuery"
'jquery': {
exports: 'jQuery'
},
"jquery-migrate": ['jquery'],
"jquery.cookie": {
deps: ["jquery"],
exports: "jQuery.fn.cookie"
'jquery-migrate': ['jquery'],
'jquery.cookie': {
deps: ['jquery'],
exports: 'jQuery.fn.cookie'
},
"jquery.timeago": {
deps: ["jquery"],
exports: "jQuery.timeago"
'jquery.timeago': {
deps: ['jquery'],
exports: 'jQuery.timeago'
},
"jquery.url": {
deps: ["jquery"],
exports: "jQuery.url"
'jquery.url': {
deps: ['jquery'],
exports: 'jQuery.url'
},
"jquery.fileupload": {
deps: ["jquery.ui", "jquery.iframe-transport"],
exports: "jQuery.fn.fileupload"
'jquery.fileupload': {
deps: ['jquery.ui', 'jquery.iframe-transport'],
exports: 'jQuery.fn.fileupload'
},
"jquery.tinymce": {
deps: ["jquery", "tinymce"],
exports: "jQuery.fn.tinymce"
'jquery.tinymce': {
deps: ['jquery', 'tinymce'],
exports: 'jQuery.fn.tinymce'
},
"backbone.paginator": {
deps: ["backbone"],
exports: "Backbone.PageableCollection"
'backbone.paginator': {
deps: ['backbone'],
exports: 'Backbone.PageableCollection'
},
"backbone-super": {
deps: ["backbone"]
'backbone-super': {
deps: ['backbone']
},
"string_utils": {
deps: ["underscore"],
exports: "interpolate_text"
'string_utils': {
deps: ['underscore'],
exports: 'interpolate_text'
},
// Needed by OVA
"video.dev": {
exports:"videojs"
'video.dev': {
exports: 'videojs'
},
"vjs.youtube": {
deps: ["video.dev"]
'vjs.youtube': {
deps: ['video.dev']
},
"rangeslider": {
deps: ["video.dev"]
'rangeslider': {
deps: ['video.dev']
},
"annotator": {
exports: "Annotator"
'annotator': {
exports: 'Annotator'
},
"annotator-harvardx":{
deps: ["annotator"]
'annotator-harvardx': {
deps: ['annotator']
},
"share-annotator": {
deps: ["annotator"]
'share-annotator': {
deps: ['annotator']
},
"richText-annotator": {
deps: ["annotator", "tinymce"]
'richText-annotator': {
deps: ['annotator', 'tinymce']
},
"reply-annotator": {
deps: ["annotator"]
'reply-annotator': {
deps: ['annotator']
},
"tags-annotator": {
deps: ["annotator"]
'tags-annotator': {
deps: ['annotator']
},
"diacritic-annotator": {
deps: ["annotator"]
'diacritic-annotator': {
deps: ['annotator']
},
"flagging-annotator": {
deps: ["annotator"]
'flagging-annotator': {
deps: ['annotator']
},
"grouping-annotator": {
deps: ["annotator"]
'grouping-annotator': {
deps: ['annotator']
},
"ova": {
exports: "ova",
'ova': {
exports: 'ova',
deps: [
"annotator", "annotator-harvardx", "video.dev", "vjs.youtube", "rangeslider", "share-annotator",
"richText-annotator", "reply-annotator", "tags-annotator", "flagging-annotator",
"grouping-annotator", "diacritic-annotator", "jquery-Watch", "catch", "handlebars", "URI"
'annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube', 'rangeslider', 'share-annotator',
'richText-annotator', 'reply-annotator', 'tags-annotator', 'flagging-annotator',
'grouping-annotator', 'diacritic-annotator', 'jquery-Watch', 'catch', 'handlebars', 'URI'
]
},
"osda": {
exports: "osda",
'osda': {
exports: 'osda',
deps: [
"annotator", "annotator-harvardx", "video.dev", "vjs.youtube", "rangeslider", "share-annotator",
"richText-annotator", "reply-annotator", "tags-annotator", "flagging-annotator",
"grouping-annotator", "diacritic-annotator", "openseadragon", "jquery-Watch", "catch", "handlebars",
"URI"
'annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube', 'rangeslider', 'share-annotator',
'richText-annotator', 'reply-annotator', 'tags-annotator', 'flagging-annotator',
'grouping-annotator', 'diacritic-annotator', 'openseadragon', 'jquery-Watch', 'catch', 'handlebars',
'URI'
]
},
"tinymce": {
exports: "tinymce"
'tinymce': {
exports: 'tinymce'
},
// End of needed by OVA
"moment": {
exports: "moment"
'moment': {
exports: 'moment'
},
"moment-with-locales": {
exports: "moment"
'moment-with-locales': {
exports: 'moment'
},
"afontgarde": {
exports: "AFontGarde"
'afontgarde': {
exports: 'AFontGarde'
},
// Because Draggabilly is being used by video code, the namespaced version of
// require is not being recognized. Therefore the library is being added to the
// global namespace instead of being registered in require.
"draggabilly": {
exports: "Draggabilly"
'draggabilly': {
exports: 'Draggabilly'
}
}
});

View File

@@ -56,9 +56,8 @@
'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix',
'coffee/src/instructor_dashboard/student_admin': 'coffee/src/instructor_dashboard/student_admin',
'xmodule_js/common_static/js/test/add_ajax_prefix': 'xmodule_js/common_static/js/test/add_ajax_prefix',
'xblock/core': 'xmodule_js/common_static/js/xblock/core',
'xblock/runtime.v1': 'xmodule_js/common_static/coffee/src/xblock/runtime.v1',
'xblock/lms.runtime.v1': 'coffee/src/xblock/lms.runtime.v1',
'xblock/lms.runtime.v1': 'lms/js/xblock/lms.runtime.v1',
'xblock': 'common/js/xblock',
'capa/display': 'xmodule_js/src/capa/display',
'string_utils': 'xmodule_js/common_static/js/src/string_utils',
'logger': 'xmodule_js/common_static/js/src/logger',

View File

@@ -0,0 +1,55 @@
(function(URI) {
'use strict';
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) {
var key;
for (key in parent) {
if (__hasProp.call(parent, key)) {
child[key] = parent[key];
}
}
function Ctor() {
this.constructor = child;
}
Ctor.prototype = parent.prototype;
child.prototype = new Ctor();
child.__super__ = parent.prototype;
return child;
};
this.LmsRuntime = {};
this.LmsRuntime.v1 = (function(_super) {
__extends(v1, _super);
function v1() {
return v1.__super__.constructor.apply(this, arguments);
}
v1.prototype.handlerUrl = function(element, handlerName, suffix, query, thirdparty) {
var courseId, handlerAuth, uri, usageId;
courseId = $(element).data('course-id');
usageId = $(element).data('usage-id');
handlerAuth = thirdparty ? 'handler_noauth' : 'handler';
uri = URI('/courses')
.segment(courseId)
.segment('xblock')
.segment(usageId)
.segment(handlerAuth)
.segment(handlerName);
if (suffix !== null) {
uri.segment(suffix);
}
if (query !== null) {
uri.search(query);
}
return uri.toString();
};
return v1;
})(XBlock.Runtime.v1);
}).call(this, URI); // jshint ignore:line

View File

@@ -5,6 +5,20 @@
.title.center-col {
padding: 0 calc( ( 100% - 750px ) / 2 ) 10px;
}
h2 {
font-size: 16px;
font-weight: 600;
text-transform: unset;
color: #4a4a4a;
margin-bottom: 40px;
.course-title {
display: block;
font-weight: 100;
font-size: 24px;
margin-top: 5px;
}
}
}
.instruction {
@@ -13,6 +27,28 @@
margin-left: auto;
margin-right: auto;
}
.instruction-info {
font-size: 24px;
font-weight: 100;
color: #57595a;
margin-bottom: 30px;
.fa-envelope-o {
color: #b92167;
font-size: 26px;
margin-right: 8px;
}
}
.activate {
font-size: 16px;
font-weight: 600;
color: #4a4a4a;
}
.activate-info {
font-size: 16px;
font-weight: 100;
color: #4a4a4a;
}
}
.payment-info {

View File

@@ -1,7 +1,7 @@
<div id="wrapper-review" tab-index="0" class="wrapper-view make-payment-step">
<div class="review view">
<% if ( !upgrade ) { %>
<h2 class="title center-col">
<h2 class="right-col">
<%= HtmlUtils.interpolateHtml(
gettext( "You are enrolling in: {courseName}"),
{ courseName: HtmlUtils.joinHtml(
@@ -27,16 +27,25 @@
</div>
<% } %>
<div class="instruction <% if ( !upgrade ) { %>center-col<% } %>">
<div class="instruction <% if ( !upgrade && isActive ) { %>center-col<% } %>">
<% if ( _.some( requirements, function( isVisible ) { return isVisible; } ) ) { %>
<p>
<p class="instruction-info">
<% if ( verificationDeadline ) { %>
<%- _.sprintf(
gettext( "You can pay now even if you don't have the following items available, but you will need to have these by %(date)s to qualify to earn a Verified Certificate." ),
{ date: verificationDeadline }
) %>
<% } else if ( !isActive ) { %>
<%- gettext( "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page." ) %>
<i class="fa fa-envelope-o" aria-hidden="true"></i>
<%= HtmlUtils.interpolateHtml(
gettext( "An email has been sent to {userEmail} with a link for you to activate your account."),
{userEmail: userEmail}
)
%>
<h3 class="activate"><%- gettext("Why activate?") %></h3>
<div class="activate-info">
<%- gettext("We ask you to activate your account to ensure it is really you creating the account and to prevent fraud.") %>
<div>
<% } else { %>
<%- gettext( "You can pay now even if you don't have the following items available, but you will need to have these to qualify to earn a Verified Certificate." ) %>
<% } %>
@@ -47,20 +56,7 @@
<% if ( requirements['account-activation-required'] || requirements['photo-id-required'] || requirements['webcam-required']) { %>
<div class="requirements-container">
<ul class="list-reqs <% if ( requirements['account-activation-required'] ) { %>account-not-activated<% } %>">
<% if ( requirements['account-activation-required'] ) { %>
<li class="req req-0 req-activate">
<h3 class="title"><%- gettext( "Activate Your Account" ) %></h3>
<div class="placeholder-art">
<span class="icon fa fa-envelope-o" aria-hidden="true"></span>
</div>
<div class="copy">
<p>
<span class="copy-super"><%- gettext( "Check Your Email" ) %></span>
</p>
</div>
</li>
<% } else {%>
<% if (!requirements['account-activation-required']) {%>
<% if ( requirements['photo-id-required'] ) { %>
<li class="req req-1 req-id">
<h3 class="title"><%- gettext( "Government-Issued Photo ID" ) %></h3>

View File

@@ -81,6 +81,7 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView
data-requirements='${json.dumps(requirements)}'
data-msg-key='${message_key}'
data-is-active='${is_active}'
data-user-email='${user_email}'
data-already-verified='${already_verified}'
data-verification-good-until='${verification_good_until}'
data-capture-sound='${capture_sound}'

View File

@@ -16,7 +16,7 @@
"underscore.string": "~3.3.4"
},
"devDependencies": {
"edx-custom-a11y-rules": "0.1.1",
"edx-custom-a11y-rules": "0.1.2",
"pa11y": "3.6.0",
"pa11y-reporter-1.0-json": "1.0.2",
"jasmine-core": "^2.4.1",

View File

@@ -126,8 +126,7 @@ class SystemTestSuite(NoseTestSuite):
self.randomize = kwargs.get('randomize', None)
if self.processes is None:
# Use one process per core for LMS tests, and no multiprocessing
# otherwise.
# Don't use multiprocessing by default
self.processes = 0
self.processes = int(self.processes)

View File

@@ -25,7 +25,7 @@ class TestSuite(object):
self.root = args[0]
self.subsuites = kwargs.get('subsuites', [])
self.failed_suites = []
self.verbosity = kwargs.get('verbosity', 1)
self.verbosity = int(kwargs.get('verbosity', 1))
self.skip_clean = kwargs.get('skip_clean', False)
self.pdb = kwargs.get('pdb', False)

View File

@@ -99,22 +99,23 @@ case "$TEST_SUITE" in
;;
"lms-unit")
LMS_ARGS="--with-flaky"
EXTRA_ARGS="--with-flaky"
PAVER_ARGS="--processes=-1 --cov_args='-p' -v"
case "$SHARD" in
"all")
paver test_system -s lms --extra_args="$LMS_ARGS" --cov_args="-p" -v
paver test_system -s lms --extra_args="$EXTRA_ARGS" $PAVER_ARGS
;;
"1")
paver test_system -s lms --extra_args="--attr='shard_1' $LMS_ARGS" --cov_args="-p" -v
paver test_system -s lms --extra_args="--attr='shard_1' $EXTRA_ARGS" $PAVER_ARGS
;;
"2")
paver test_system -s lms --extra_args="--attr='shard_2' $LMS_ARGS" --cov_args="-p" -v
paver test_system -s lms --extra_args="--attr='shard_2' $EXTRA_ARGS" $PAVER_ARGS
;;
"3")
paver test_system -s lms --extra_args="--attr='shard_3' $LMS_ARGS" --cov_args="-p" -v
paver test_system -s lms --extra_args="--attr='shard_3' $EXTRA_ARGS" $PAVER_ARGS
;;
"4")
paver test_system -s lms --extra_args="--attr='shard_1=False,shard_2=False,shard_3=False' $LMS_ARGS" --cov_args="-p" -v
paver test_system -s lms --extra_args="--attr='shard_1=False,shard_2=False,shard_3=False' $EXTRA_ARGS" $PAVER_ARGS
;;
*)
# If no shard is specified, rather than running all tests, create an empty xunit file. This is a