diff --git a/cms/djangoapps/contentstore/features/common.py b/cms/djangoapps/contentstore/features/common.py index 70ce70d0aedb..686c8ec1562d 100644 --- a/cms/djangoapps/contentstore/features/common.py +++ b/cms/djangoapps/contentstore/features/common.py @@ -247,7 +247,6 @@ def create_unit_from_course_outline(): world.css_click(selector) world.wait_for_mathjax() - world.wait_for_xmodule() world.wait_for_loading() assert world.is_css_present('ul.new-component-type') diff --git a/cms/djangoapps/pipeline_js/js/xmodule.js b/cms/djangoapps/pipeline_js/js/xmodule.js index a9c16a336363..881b6482a1f5 100644 --- a/cms/djangoapps/pipeline_js/js/xmodule.js +++ b/cms/djangoapps/pipeline_js/js/xmodule.js @@ -52,9 +52,9 @@ define( return deferred.promise(); } - if (!window.xmoduleUrls) { - throw Error('window.xmoduleUrls must be defined'); - } - return requireQueue(window.xmoduleUrls); + // if (!window.xmoduleUrls) { + // throw Error('window.xmoduleUrls must be defined'); + // } + return requireQueue([]); } ); diff --git a/cms/envs/acceptance.py b/cms/envs/acceptance.py index 514e4a7d9d88..766496f4865c 100644 --- a/cms/envs/acceptance.py +++ b/cms/envs/acceptance.py @@ -110,10 +110,6 @@ def seed(): # We do not yet understand why this occurs. Setting this to true is a stopgap measure USE_I18N = True -# Override the test stub webpack_loader that is installed in test.py. -INSTALLED_APPS = [app for app in INSTALLED_APPS if app != 'openedx.tests.util.webpack_loader'] -INSTALLED_APPS.append('webpack_loader') - # Include the lettuce app for acceptance testing, including the 'harvest' django-admin command # django.contrib.staticfiles used to be loaded by lettuce, now we must add it ourselves # django.contrib.staticfiles is not added to lms as there is a ^/static$ route built in to the app diff --git a/cms/envs/test.py b/cms/envs/test.py index 6a1e05f7ceab..ed891b320b52 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -54,8 +54,6 @@ # Want static files in the same dir for running on jenkins. STATIC_ROOT = TEST_ROOT / "staticfiles" -INSTALLED_APPS = [app for app in INSTALLED_APPS if app != 'webpack_loader'] -INSTALLED_APPS.append('openedx.tests.util.webpack_loader') WEBPACK_LOADER['DEFAULT']['STATS_FILE'] = STATIC_ROOT / "webpack-stats.json" GITHUB_REPO_ROOT = TEST_ROOT / "data" diff --git a/cms/static/karma_cms_webpack.conf.js b/cms/static/karma_cms_webpack.conf.js new file mode 100644 index 000000000000..c2c4ce01261a --- /dev/null +++ b/cms/static/karma_cms_webpack.conf.js @@ -0,0 +1,55 @@ +/* eslint-env node */ + +// Karma config for cms suite. +// Docs and troubleshooting tips in common/static/common/js/karma.common.conf.js + +'use strict'; +var path = require('path'); +var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js')); + +var options = { + + includeCommonFiles: true, + + libraryFiles: [], + + libraryFilesToInclude: [ + ], + + // 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/factories/login.js', webpack: true}, + // {pattern: 'js/factories/xblock_validation.js', webpack: true}, + // {pattern: 'js/factories/container.js', webpack: true}, + // {pattern: 'js/factories/context_course.js', webpack: true}, + // {pattern: 'js/factories/edit_tabs.js', webpack: true}, + // {pattern: 'js/factories/library.js', webpack: true}, + // {pattern: 'js/factories/textbooks.js', webpack: true}, + // ], + + // All spec files should be imported in main_webpack.js, rather than being listed here + specFiles: [], + + fixtureFiles: [ + {pattern: '../templates/js/**/*.underscore'}, + {pattern: 'templates/**/*.underscore'} + ], + + runFiles: [ + {pattern: 'cms/js/spec/main_webpack.js', webpack: true}, + {pattern: 'jasmine.cms.conf.js', included: true} + ], + + preprocessors: {} +}; + +options.runFiles + .filter(function(file) { return file.webpack; }) + .forEach(function(file) { + options.preprocessors[file.pattern] = ['webpack']; + }); + +module.exports = function(config) { + configModule.configure(config, options); +}; diff --git a/cms/templates/container.html b/cms/templates/container.html index 0d0a4095e09e..b2ecac361671 100644 --- a/cms/templates/container.html +++ b/cms/templates/container.html @@ -43,20 +43,18 @@ <%block name="page_bundle"> - - <%static:invoke_page_bundle page_name="js/pages/container" class_name="ContainerFactory"> - ${component_templates | n, dump_js_escaped_json}, - ${xblock_info | n, dump_js_escaped_json}, - "${action | n, js_escaped_string}", - { - isUnitPage: ${is_unit_page | n, dump_js_escaped_json}, - canEdit: true, - outlineURL: "${outline_url | n, js_escaped_string}" - } - + <%static:webpack entry="js/factories/container"> + ContainerFactory( + ${component_templates | n, dump_js_escaped_json}, + ${xblock_info | n, dump_js_escaped_json}, + "${action | n, js_escaped_string}", + { + isUnitPage: ${is_unit_page | n, dump_js_escaped_json}, + canEdit: true, + outlineURL: "${outline_url | n, js_escaped_string}" + } + ); + <%block name="content"> diff --git a/cms/templates/edit-tabs.html b/cms/templates/edit-tabs.html index 9541f07c35bc..07500296dc6a 100644 --- a/cms/templates/edit-tabs.html +++ b/cms/templates/edit-tabs.html @@ -19,8 +19,8 @@ % endfor -<%block name="requirejs"> - require(["js/factories/edit_tabs"], function (EditTabsFactory) { +<%block name="page_bundle"> + <%static:webpack entry="js/factories/edit_tabs"> EditTabsFactory("${context_course.location | n, js_escaped_string}", "${reverse('tabs_handler', kwargs={'course_key_string': context_course.id})}"); }); diff --git a/cms/templates/library.html b/cms/templates/library.html index 64f91662db58..b293697bfd3c 100644 --- a/cms/templates/library.html +++ b/cms/templates/library.html @@ -25,8 +25,8 @@ -<%block name="requirejs"> - require(["js/factories/library"], function(LibraryFactory) { +<%block name="page_bundle"> + <%static:webpack entry="js/factories/library"> LibraryFactory( ${component_templates | n, dump_js_escaped_json}, ${xblock_info | n, dump_js_escaped_json}, diff --git a/cms/templates/studio_xblock_wrapper.html b/cms/templates/studio_xblock_wrapper.html index 66afb2aee9b0..18cda07d7a4a 100644 --- a/cms/templates/studio_xblock_wrapper.html +++ b/cms/templates/studio_xblock_wrapper.html @@ -7,6 +7,7 @@ from openedx.core.djangolib.js_utils import ( dump_js_escaped_json, js_escaped_string ) +from xmodule.x_module import XModule, XModuleDescriptor %> <% xblock_url = xblock_studio_url(xblock) @@ -38,6 +39,10 @@ }); +% if isinstance(xblock, (XModule, XModuleDescriptor)): + <%static:webpack entry="${getattr(xblock.__class__, 'unmixed_class', xblock.__class__).__name__}"/> +% endif + % if not is_root: % if is_reorderable:
  • diff --git a/common/lib/conftest.py b/common/lib/conftest.py index 54d4a8ecdf81..39c59426f707 100644 --- a/common/lib/conftest.py +++ b/common/lib/conftest.py @@ -3,3 +3,16 @@ # Patch the xml libs before anything else. from safe_lxml import defuse_xml_libs defuse_xml_libs() + +import pytest + +@pytest.fixture(autouse=True) +def no_webpack_loader(monkeypatch): + monkeypatch.setattr( + "webpack_loader.templatetags.webpack_loader.render_bundle", + lambda entry, extension=None, config='DEFAULT', attrs='': '' + ) + monkeypatch.setattr( + "webpack_loader.utils.get_as_tags", + lambda entry, extension=None, config='DEFAULT', attrs='': [] + ) diff --git a/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js b/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js index ca2dbc52403e..a02ca250d248 100644 --- a/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js +++ b/common/lib/xmodule/xmodule/assets/vertical/public/js/vertical_student_view.js @@ -1,7 +1,6 @@ /* JavaScript for Vertical Student View. */ /* global Set:false */ // false means do not assign to Set -/* global ViewedEventTracker:false */ // The vertical marks blocks complete if they are completable by viewing. The // global variable SEEN_COMPLETABLES tracks blocks between separate loads of @@ -9,62 +8,61 @@ // navigates back within a given sequential) to protect against duplicate calls // to the server. +import BookmarkButton from 'course_bookmarks/js/views/bookmark_button'; +import {ViewedEventTracker} from '../../../../../../../../lms/static/completion/js/ViewedEvent.js'; var SEEN_COMPLETABLES = new Set(); window.VerticalStudentView = function(runtime, element) { 'use strict'; - RequireJS.require(['course_bookmarks/js/views/bookmark_button'], function(BookmarkButton) { - var $element = $(element); - var $bookmarkButtonElement = $element.find('.bookmark-button'); - return new BookmarkButton({ - el: $bookmarkButtonElement, - bookmarkId: $bookmarkButtonElement.data('bookmarkId'), - usageId: $element.data('usageId'), - bookmarked: $element.parent('#seq_content').data('bookmarked'), - apiUrl: $bookmarkButtonElement.data('bookmarksApiUrl') - }); + var $element = $(element); + var $bookmarkButtonElement = $element.find('.bookmark-button'); + return new BookmarkButton({ + el: $bookmarkButtonElement, + bookmarkId: $bookmarkButtonElement.data('bookmarkId'), + usageId: $element.data('usageId'), + bookmarked: $element.parent('#seq_content').data('bookmarked'), + apiUrl: $bookmarkButtonElement.data('bookmarksApiUrl') }); - RequireJS.require(['bundles/ViewedEvent'], function() { - var tracker, vertical, viewedAfter; - var completableBlocks = []; - var vertModDivs = element.getElementsByClassName('vert-mod'); - if (vertModDivs.length === 0) { - return; - } - vertical = vertModDivs[0]; - $(element).find('.vert').each(function(idx, block) { - if (block.dataset.completableByViewing !== undefined) { - completableBlocks.push(block); - } - }); - if (completableBlocks.length > 0) { - viewedAfter = parseInt(vertical.dataset.completionDelayMs, 10); - if (!(viewedAfter >= 0)) { - // parseInt will return NaN if it fails to parse, which is not >= 0. - viewedAfter = 5000; - } - tracker = new ViewedEventTracker(completableBlocks, viewedAfter); - tracker.addHandler(function(block, event) { - var blockKey = block.dataset.id; - if (blockKey && !SEEN_COMPLETABLES.has(blockKey)) { - if (event.elementHasBeenViewed) { - $.ajax({ - type: 'POST', - url: runtime.handlerUrl(element, 'publish_completion'), - data: JSON.stringify({ - block_key: blockKey, - completion: 1.0 - }) - }).then( - function() { - SEEN_COMPLETABLES.add(blockKey); - } - ); - } - } - }); + var tracker, vertical, viewedAfter; + var completableBlocks = []; + var vertModDivs = element.getElementsByClassName('vert-mod'); + if (vertModDivs.length === 0) { + return; + } + vertical = vertModDivs[0]; + $(element).find('.vert').each(function(idx, block) { + if (block.dataset.completableByViewing !== undefined) { + completableBlocks.push(block); } }); + if (completableBlocks.length > 0) { + viewedAfter = parseInt(vertical.dataset.completionDelayMs, 10); + if (!(viewedAfter >= 0)) { + // parseInt will return NaN if it fails to parse, which is not >= 0. + viewedAfter = 5000; + } + tracker = new ViewedEventTracker(completableBlocks, viewedAfter); + tracker.addHandler(function(block, event) { + var blockKey = block.dataset.id; + + if (blockKey && !SEEN_COMPLETABLES.has(blockKey)) { + if (event.elementHasBeenViewed) { + $.ajax({ + type: 'POST', + url: runtime.handlerUrl(element, 'publish_completion'), + data: JSON.stringify({ + block_key: blockKey, + completion: 1.0 + }) + }).then( + function() { + SEEN_COMPLETABLES.add(blockKey); + } + ); + } + } + }); + } }; diff --git a/common/lib/xmodule/xmodule/js/fixtures/video.html b/common/lib/xmodule/xmodule/js/fixtures/video.html index 562aa82a3e2e..7dd54c16fa7f 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video.html @@ -13,17 +13,18 @@
    -
    +
    -
    +
    - +
    diff --git a/common/lib/xmodule/xmodule/js/fixtures/video_autoadvance.html b/common/lib/xmodule/xmodule/js/fixtures/video_autoadvance.html index d6deeaf3d569..bbc07e5afbf6 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video_autoadvance.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_autoadvance.html @@ -19,6 +19,7 @@
    +
    +
    +
    +