Commit c5df4aa6 by Brian Jacobel

Work on getting Karma to run

parent 57e82506
{ {
"presets": [ "presets": [
["env", { [
"targets": { "env",
"browsers": [ {
"last 2 versions", "targets": {
"IE >= 11" "browsers": [
] "last 2 versions",
}, "IE >= 11"
"useBuiltIns": true, ]
"modules": false, },
"exclude": [ "modules": "commonjs"
"transform-regenerator" }
] ]
}],
"react"
],
"plugins": [
"transform-object-rest-spread"
] ]
} }
...@@ -58,3 +58,5 @@ common/lib/xmodule/xmodule/js/src/vertical/edit.js ...@@ -58,3 +58,5 @@ common/lib/xmodule/xmodule/js/src/vertical/edit.js
# This file is responsible for almost half of the repo's total issues. # This file is responsible for almost half of the repo's total issues.
common/lib/xmodule/xmodule/js/src/capa/schematic.js common/lib/xmodule/xmodule/js/src/capa/schematic.js
!**/.eslintrc.js
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
var path = require('path'); var path = require('path');
var _ = require('underscore'); var _ = require('underscore');
var appRoot = path.join(__dirname, '../../../../'); var appRoot = path.join(__dirname, '../../../../');
var webpackConfig = require(path.join(appRoot, 'webpack.config.js'));
delete webpackConfig.entry;
// Files which are needed by all lms/cms suites. // Files which are needed by all lms/cms suites.
var commonFiles = { var commonFiles = {
...@@ -177,13 +180,15 @@ var defaultNormalizeFunc = function(appRoot, pattern) { ...@@ -177,13 +180,15 @@ var defaultNormalizeFunc = function(appRoot, pattern) {
return pattern; return pattern;
}; };
var normalizePathsForCoverage = function(files, normalizeFunc) { var normalizePathsForCoverage = function(files, normalizeFunc, preprocessors) {
var normalizeFn = normalizeFunc || defaultNormalizeFunc, var normalizeFn = normalizeFunc || defaultNormalizeFunc,
normalizedFile,
filesForCoverage = {}; filesForCoverage = {};
files.forEach(function(file) { files.forEach(function(file) {
if (!file.ignoreCoverage) { if (!file.ignoreCoverage) {
filesForCoverage[normalizeFn(appRoot, file.pattern)] = ['coverage']; normalizedFile = normalizeFn(appRoot, file.pattern);
filesForCoverage[normalizedFile] = ['coverage'].concat(preprocessors[normalizedFile] || []);
} }
}); });
...@@ -191,29 +196,16 @@ var normalizePathsForCoverage = function(files, normalizeFunc) { ...@@ -191,29 +196,16 @@ var normalizePathsForCoverage = function(files, normalizeFunc) {
}; };
/** /**
* Sets nocache on each file in the list.
* @param {Object} files
* @param {Bool} enable
* @return {Object}
*/
var setNocache = function(files, enable) {
files.forEach(function(f) {
if (_.isObject(f)) {
f.nocache = enable;
}
});
return files;
};
/**
* Sets defaults for each file pattern. * Sets defaults for each file pattern.
* RequireJS files are excluded by default.
* Webpack files are included by default.
* @param {Object} files * @param {Object} files
* @return {Object} * @return {Object}
*/ */
var setDefaults = function(files) { var setDefaults = function(files) {
return files.map(function(f) { return files.map(function(f) {
var file = _.isObject(f) ? f : {pattern: f}; var file = _.isObject(f) ? f : {pattern: f};
if (!file.included) { if (!file.included && !file.webpack) {
f.included = false; f.included = false;
} }
return file; return file;
...@@ -281,6 +273,8 @@ var getBaseConfig = function(config, useRequireJs) { ...@@ -281,6 +273,8 @@ var getBaseConfig = function(config, useRequireJs) {
'karma-chrome-launcher', 'karma-chrome-launcher',
'karma-firefox-launcher', 'karma-firefox-launcher',
'karma-spec-reporter', 'karma-spec-reporter',
'karma-webpack',
'karma-sourcemap-loader',
customPlugin customPlugin
], ],
...@@ -349,7 +343,9 @@ var getBaseConfig = function(config, useRequireJs) { ...@@ -349,7 +343,9 @@ var getBaseConfig = function(config, useRequireJs) {
client: { client: {
captureConsole: false captureConsole: false
} },
webpack: webpackConfig
}; };
}; };
...@@ -382,11 +378,6 @@ var configure = function(config, options) { ...@@ -382,11 +378,6 @@ var configure = function(config, options) {
// We set it to false by default because RequireJS should be used instead. // We set it to false by default because RequireJS should be used instead.
files = setDefaults(files); files = setDefaults(files);
// With nocache=true, Karma always serves the latest files from disk.
// However, that prevents coverage tracking from working.
// So we only set it if coverage tracking is off.
setNocache(files, !config.coverage);
var filesForCoverage = _.flatten( var filesForCoverage = _.flatten(
_.map( _.map(
['sourceFiles', 'specFiles'], ['sourceFiles', 'specFiles'],
...@@ -399,7 +390,7 @@ var configure = function(config, options) { ...@@ -399,7 +390,7 @@ var configure = function(config, options) {
var preprocessors = _.extend( var preprocessors = _.extend(
{}, {},
options.preprocessors, options.preprocessors,
normalizePathsForCoverage(filesForCoverage, options.normalizePathsForCoverageFunc) normalizePathsForCoverage(filesForCoverage, options.normalizePathsForCoverageFunc, options.preprocessors)
); );
config.set(_.extend(baseConfig, { config.set(_.extend(baseConfig, {
......
...@@ -28,7 +28,6 @@ var options = { ...@@ -28,7 +28,6 @@ var options = {
sourceFiles: [ sourceFiles: [
{pattern: 'coffee/src/**/!(*spec).js'}, {pattern: 'coffee/src/**/!(*spec).js'},
{pattern: 'course_bookmarks/**/!(*spec).js'}, {pattern: 'course_bookmarks/**/!(*spec).js'},
{pattern: 'course_experience/js/**/!(*spec).js'},
{pattern: 'discussion/js/**/!(*spec).js'}, {pattern: 'discussion/js/**/!(*spec).js'},
{pattern: 'js/**/!(*spec|djangojs).js'}, {pattern: 'js/**/!(*spec|djangojs).js'},
{pattern: 'lms/js/**/!(*spec).js'}, {pattern: 'lms/js/**/!(*spec).js'},
...@@ -37,7 +36,8 @@ var options = { ...@@ -37,7 +36,8 @@ var options = {
], ],
specFiles: [ specFiles: [
{pattern: '../**/*spec.js'} {pattern: '../**/*spec.js'},
{pattern: 'course_experience/js/**/*_spec.js', webpack: true}
], ],
fixtureFiles: [ fixtureFiles: [
...@@ -49,9 +49,17 @@ var options = { ...@@ -49,9 +49,17 @@ var options = {
runFiles: [ runFiles: [
{pattern: 'lms/js/spec/main.js', included: true} {pattern: 'lms/js/spec/main.js', included: true}
] ],
preprocessors: {}
}; };
options.specFiles
.filter(function(file) { return file.webpack; })
.forEach(function(file) {
options.preprocessors[file.pattern] = ['webpack', 'sourcemap'];
});
module.exports = function(config) { module.exports = function(config) {
configModule.configure(config, options); configModule.configure(config, options);
}; };
...@@ -676,7 +676,6 @@ ...@@ -676,7 +676,6 @@
'course_bookmarks/js/spec/bookmark_button_view_spec.js', 'course_bookmarks/js/spec/bookmark_button_view_spec.js',
'course_bookmarks/js/spec/bookmarks_list_view_spec.js', 'course_bookmarks/js/spec/bookmarks_list_view_spec.js',
'course_bookmarks/js/spec/course_bookmarks_factory_spec.js', 'course_bookmarks/js/spec/course_bookmarks_factory_spec.js',
'course_experience/js/spec/course_outline_factory_spec.js',
'discussion/js/spec/discussion_board_factory_spec.js', 'discussion/js/spec/discussion_board_factory_spec.js',
'discussion/js/spec/discussion_profile_page_factory_spec.js', 'discussion/js/spec/discussion_profile_page_factory_spec.js',
'discussion/js/spec/discussion_board_view_spec.js', 'discussion/js/spec/discussion_board_view_spec.js',
......
module.exports = {
extends: 'eslint-config-edx',
root: true,
};
import * as constants from 'edx-ui-toolkit/src/js/utils/constants'; import * as constants from 'edx-ui-toolkit/src/js/utils/constants';
import * as Logger from logger; import log from 'logger';
export class CourseOutline { export class CourseOutline {
constructor(root) { constructor(root) {
...@@ -8,19 +8,19 @@ export class CourseOutline { ...@@ -8,19 +8,19 @@ export class CourseOutline {
const currentFocusIndex = focusable.indexOf(event.target); const currentFocusIndex = focusable.indexOf(event.target);
switch (event.keyCode) { // eslint-disable-line default-case switch (event.keyCode) { // eslint-disable-line default-case
case constants.keyCodes.down: case constants.keyCodes.down:
event.preventDefault(); event.preventDefault();
focusable[Math.min(currentFocusIndex + 1, focusable.length - 1)].focus(); focusable[Math.min(currentFocusIndex + 1, focusable.length - 1)].focus();
break; break;
case constants.keyCodes.up: case constants.keyCodes.up:
event.preventDefault(); event.preventDefault();
focusable[Math.max(currentFocusIndex - 1, 0)].focus(); focusable[Math.max(currentFocusIndex - 1, 0)].focus();
break; break;
} }
}); });
document.querySelectorAll('a:not([href^="#"])').addEventListener('click', (event) => { document.querySelectorAll('a:not([href^="#"])').addEventListener('click', (event) => {
Logger.log( log(
'edx.ui.lms.link_clicked', 'edx.ui.lms.link_clicked',
{ {
current_url: window.location.href, current_url: window.location.href,
......
import * as constants from "edx-ui-toolkit/js/utils/constants";
import log from 'logger';
import { CourseOutline } from "../CourseOutline";
describe('Course outline factory', () => {
describe('keyboard listener', () => {
const triggerKeyListener = (current, destination, keyCode) => {
current.focus();
spyOn(destination, 'focus');
$('.block-tree').trigger(
$.Event('keydown', {
keyCode,
target: current,
}),
);
};
beforeEach(() => {
loadFixtures('course_experience/fixtures/course-outline-fragment.html');
new CourseOutline('.block-tree');
});
describe('when the down arrow is pressed', () => {
it('moves focus from a subsection to the next subsection in the outline', () => {
const current = $('a.focusable:contains("Homework - Labs and Demos")')[0];
const destination = $('a.focusable:contains("Homework - Essays")')[0];
triggerKeyListener(current, destination, constants.keyCodes.down);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus to the section list if at a section boundary', () => {
const current = $('li.focusable:contains("Example Week 3: Be Social")')[0];
const destination = $('ol.focusable:contains("Lesson 3 - Be Social")')[0];
triggerKeyListener(current, destination, constants.keyCodes.down);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus to the next section if on the last subsection', () => {
const current = $('a.focusable:contains("Homework - Essays")')[0];
const destination = $('li.focusable:contains("Example Week 3: Be Social")')[0];
triggerKeyListener(current, destination, constants.keyCodes.down);
expect(destination.focus).toHaveBeenCalled();
});
});
describe('when the up arrow is pressed', () => {
it('moves focus from a subsection to the previous subsection in the outline', () => {
const current = $('a.focusable:contains("Homework - Essays")')[0];
const destination = $('a.focusable:contains("Homework - Labs and Demos")')[0];
triggerKeyListener(current, destination, constants.keyCodes.up);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus to the section group if at the first subsection', () => {
const current = $('a.focusable:contains("Lesson 3 - Be Social")')[0];
const destination = $('ol.focusable:contains("Lesson 3 - Be Social")')[0];
triggerKeyListener(current, destination, constants.keyCodes.up);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus last subsection of the previous section if at a section boundary', () => {
const current = $('li.focusable:contains("Example Week 3: Be Social")')[0];
const destination = $('a.focusable:contains("Homework - Essays")')[0];
triggerKeyListener(current, destination, constants.keyCodes.up);
expect(destination.focus).toHaveBeenCalled();
});
});
});
describe("eventing", function() {
beforeEach(function() {
loadFixtures("course_experience/fixtures/course-outline-fragment.html");
CourseOutlineFactory(".block-tree");
spyOn(Logger, "log");
});
it("sends an event when an outline section is clicked", function() {
$('a.focusable:contains("Homework - Labs and Demos")').click();
expect(Logger.log).toHaveBeenCalledWith("edx.ui.lms.link_clicked", {
target_url: (
window.location.origin +
"/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type" +
"@sequential+block@graded_simulations"
),
current_url: window.location.toString()
});
});
});
});
define([
'jquery',
'logger',
'edx-ui-toolkit/js/utils/constants',
'course_experience/js/course_outline_factory'
],
function($, Logger, constants, CourseOutlineFactory) {
'use strict';
describe('Course outline factory', function() {
describe('keyboard listener', function() {
var triggerKeyListener = function(current, destination, keyCode) {
current.focus();
spyOn(destination, 'focus');
$('.block-tree').trigger($.Event('keydown', {
keyCode: keyCode,
target: current
}));
};
beforeEach(function() {
loadFixtures('course_experience/fixtures/course-outline-fragment.html');
CourseOutlineFactory('.block-tree');
});
describe('when the down arrow is pressed', function() {
it('moves focus from a subsection to the next subsection in the outline', function() {
var current = $('a.focusable:contains("Homework - Labs and Demos")')[0],
destination = $('a.focusable:contains("Homework - Essays")')[0];
triggerKeyListener(current, destination, constants.keyCodes.down);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus to the section list if at a section boundary', function() {
var current = $('li.focusable:contains("Example Week 3: Be Social")')[0],
destination = $('ol.focusable:contains("Lesson 3 - Be Social")')[0];
triggerKeyListener(current, destination, constants.keyCodes.down);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus to the next section if on the last subsection', function() {
var current = $('a.focusable:contains("Homework - Essays")')[0],
destination = $('li.focusable:contains("Example Week 3: Be Social")')[0];
triggerKeyListener(current, destination, constants.keyCodes.down);
expect(destination.focus).toHaveBeenCalled();
});
});
describe('when the up arrow is pressed', function() {
it('moves focus from a subsection to the previous subsection in the outline', function() {
var current = $('a.focusable:contains("Homework - Essays")')[0],
destination = $('a.focusable:contains("Homework - Labs and Demos")')[0];
triggerKeyListener(current, destination, constants.keyCodes.up);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus to the section group if at the first subsection', function() {
var current = $('a.focusable:contains("Lesson 3 - Be Social")')[0],
destination = $('ol.focusable:contains("Lesson 3 - Be Social")')[0];
triggerKeyListener(current, destination, constants.keyCodes.up);
expect(destination.focus).toHaveBeenCalled();
});
it('moves focus last subsection of the previous section if at a section boundary', function() {
var current = $('li.focusable:contains("Example Week 3: Be Social")')[0],
destination = $('a.focusable:contains("Homework - Essays")')[0];
triggerKeyListener(current, destination, constants.keyCodes.up);
expect(destination.focus).toHaveBeenCalled();
});
});
});
describe('eventing', function() {
beforeEach(function() {
loadFixtures('course_experience/fixtures/course-outline-fragment.html');
CourseOutlineFactory('.block-tree');
spyOn(Logger, 'log');
});
it('sends an event when an outline section is clicked', function() {
$('a.focusable:contains("Homework - Labs and Demos")').click();
expect(Logger.log).toHaveBeenCalledWith('edx.ui.lms.link_clicked', {
target_url: window.location.origin +
'/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type' +
'@sequential+block@graded_simulations',
current_url: window.location.toString()
});
});
});
});
}
);
...@@ -22,13 +22,9 @@ ...@@ -22,13 +22,9 @@
"devDependencies": { "devDependencies": {
"babel-core": "^6.23.0", "babel-core": "^6.23.0",
"babel-loader": "^6.4.0", "babel-loader": "^6.4.0",
"babel-plugin-react": "^1.0.0",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.2.1", "babel-preset-env": "^1.2.1",
"babel-preset-react": "^6.23.0",
"edx-custom-a11y-rules": "0.1.3", "edx-custom-a11y-rules": "0.1.3",
"eslint-config-edx": "^2.0.0", "eslint-config-edx": "^2.0.1",
"eslint-config-edx-es5": "^2.0.0", "eslint-config-edx-es5": "^2.0.0",
"jasmine-core": "^2.4.1", "jasmine-core": "^2.4.1",
"jasmine-jquery": "^2.1.1", "jasmine-jquery": "^2.1.1",
...@@ -40,11 +36,13 @@ ...@@ -40,11 +36,13 @@
"karma-jasmine-html-reporter": "^0.2.0", "karma-jasmine-html-reporter": "^0.2.0",
"karma-junit-reporter": "^0.4.1", "karma-junit-reporter": "^0.4.1",
"karma-requirejs": "^0.2.6", "karma-requirejs": "^0.2.6",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "^0.0.20", "karma-spec-reporter": "^0.0.20",
"karma-webpack": "^2.0.3",
"pa11y": "4.0.1", "pa11y": "4.0.1",
"pa11y-reporter-json-oldnode": "1.0.0", "pa11y-reporter-json-oldnode": "1.0.0",
"plato": "1.2.2", "plato": "1.2.2",
"sinon": "1.17.3 || >1.17.4 <2.0.0", "sinon": "^1.17.7",
"squirejs": "^0.1.0", "squirejs": "^0.1.0",
"webpack": "^2.2.1", "webpack": "^2.2.1",
"webpack-bundle-tracker": "^0.2.0" "webpack-bundle-tracker": "^0.2.0"
......
...@@ -12,11 +12,13 @@ const wpconfig = { ...@@ -12,11 +12,13 @@ const wpconfig = {
}, },
output: { output: {
path: path.resolve(__dirname, 'common/static/bundles'), path: path.resolve(__dirname, 'common/static/bundles'),
filename: '[name]-[hash].js', filename: '[name]-[hash].js',
libraryTarget: 'window', libraryTarget: 'window',
}, },
devtool: isProd ? false : 'cheap-eval-source-map',
plugins: [ plugins: [
new webpack.NoEmitOnErrorsPlugin(), new webpack.NoEmitOnErrorsPlugin(),
new webpack.NamedModulesPlugin(), new webpack.NamedModulesPlugin(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment