Commit ef4b5cb8 by Brian Jacobel

Clean up spec and feature; both pass lint and run in Karma

parent c5df4aa6
......@@ -9,7 +9,7 @@
"IE >= 11"
]
},
"modules": "commonjs"
"modules": false
}
]
]
......
......@@ -170,7 +170,8 @@ function junitSettings(config) {
* @param {String} pattern
* @return {String}
*/
var defaultNormalizeFunc = function(appRoot, pattern) {
// I'd like to change fix the no-shadow violation on the next line, but it would break this shared conf's API.
function defaultNormalizeFunc(appRoot, pattern) { // eslint-disable-line no-shadow
if (pattern.match(/^common\/js/)) {
pattern = path.join(appRoot, '/common/static/' + pattern);
} else if (pattern.match(/^xmodule_js\/common_static/)) {
......@@ -178,9 +179,9 @@ var defaultNormalizeFunc = function(appRoot, pattern) {
pattern.replace(/^xmodule_js\/common_static\//, ''));
}
return pattern;
};
}
var normalizePathsForCoverage = function(files, normalizeFunc, preprocessors) {
function normalizePathsForCoverage(files, normalizeFunc, preprocessors) {
var normalizeFn = normalizeFunc || defaultNormalizeFunc,
normalizedFile,
filesForCoverage = {};
......@@ -193,7 +194,7 @@ var normalizePathsForCoverage = function(files, normalizeFunc, preprocessors) {
});
return filesForCoverage;
};
}
/**
* Sets defaults for each file pattern.
......@@ -202,7 +203,7 @@ var normalizePathsForCoverage = function(files, normalizeFunc, preprocessors) {
* @param {Object} files
* @return {Object}
*/
var setDefaults = function(files) {
function setDefaults(files) {
return files.map(function(f) {
var file = _.isObject(f) ? f : {pattern: f};
if (!file.included && !file.webpack) {
......@@ -210,9 +211,9 @@ var setDefaults = function(files) {
}
return file;
});
};
}
var getBaseConfig = function(config, useRequireJs) {
function getBaseConfig(config, useRequireJs) {
var getFrameworkFiles = function() {
var files = [
'node_modules/jquery/dist/jquery.js',
......@@ -347,9 +348,9 @@ var getBaseConfig = function(config, useRequireJs) {
webpack: webpackConfig
};
};
}
var configure = function(config, options) {
function configure(config, options) {
var useRequireJs = options.useRequireJs === undefined ? true : useRequireJs,
baseConfig = getBaseConfig(config, useRequireJs);
......@@ -397,7 +398,7 @@ var configure = function(config, options) {
files: files,
preprocessors: preprocessors
}));
};
}
module.exports = {
configure: configure,
......
import * as constants from 'edx-ui-toolkit/src/js/utils/constants';
import log from 'logger';
/* globals Logger */
export class CourseOutline {
constructor(root) {
document.querySelector(root).addEventListener('keydown', (event) => {
const focusable = [...document.querySelectorAll('.outline-item.focusable')];
const currentFocusIndex = focusable.indexOf(event.target);
// import constants from 'edx-ui-toolkit/src/js/utils/constants';
switch (event.keyCode) { // eslint-disable-line default-case
case constants.keyCodes.down:
// @TODO: Figure out how to make webpack handle default exports when libraryTarget: 'window'
export class CourseOutline { // eslint-disable-line import/prefer-default-export
constructor() {
const focusable = [...document.querySelectorAll('.outline-item.focusable')];
focusable.forEach(el => el.addEventListener('keydown', (event) => {
const index = focusable.indexOf(event.target);
switch (event.key) { // eslint-disable-line default-case
case 'ArrowDown': // @TODO: Get these from the UI Toolkit
event.preventDefault();
focusable[Math.min(currentFocusIndex + 1, focusable.length - 1)].focus();
focusable[Math.min(index + 1, focusable.length - 1)].focus();
break;
case constants.keyCodes.up:
case 'ArrowUp': // @TODO: Get these from the UI Toolkit
event.preventDefault();
focusable[Math.max(currentFocusIndex - 1, 0)].focus();
focusable[Math.max(index - 1, 0)].focus();
break;
}
});
}));
document.querySelectorAll('a:not([href^="#"])').addEventListener('click', (event) => {
log(
'edx.ui.lms.link_clicked',
{
current_url: window.location.href,
target_url: event.currentTarget.href
}
document.querySelectorAll('a:not([href^="#"])')
.forEach(link => link.addEventListener('click', (event) => {
Logger.log(
'edx.ui.lms.link_clicked',
{
current_url: window.location.href,
target_url: event.currentTarget.href,
},
);
});
}),
);
}
}
import * as constants from "edx-ui-toolkit/js/utils/constants";
import log from 'logger';
import { CourseOutline } from "../CourseOutline";
/* globals Logger, loadFixtures */
// import constants from 'edx-ui-toolkit/src/js/utils/constants';
import { CourseOutline } from '../CourseOutline';
describe('Course outline factory', () => {
let outline; // eslint-disable-line no-unused-vars
// Our block IDs are invalid DOM selectors unless we first escape `:`, `+` and `@`
const escapeIds = idObj => Object.assign({}, ...Object.keys(idObj).map(key => ({
[key]: idObj[key]
.replace(/@/g, '\\@')
.replace(/:/, '\\:')
.replace(/\+/g, '\\+'),
})));
const outlineIds = escapeIds({
homeworkLabsAndDemos: 'a#block-v1:edX+DemoX+Demo_Course+type@sequential+block@graded_simulations',
homeworkEssays: 'a#block-v1:edX+DemoX+Demo_Course+type@sequential+block@175e76c4951144a29d46211361266e0e',
lesson3BeSocial: 'a#block-v1:edX+DemoX+Demo_Course+type@sequential+block@48ecb924d7fe4b66a230137626bfa93e',
exampleWeek3BeSocial: 'li#block-v1:edX+DemoX+Demo_Course+type@chapter+block@social_integration',
});
describe('keyboard listener', () => {
const triggerKeyListener = (current, destination, keyCode) => {
const triggerKeyListener = (current, destination, key) => {
current.focus();
spyOn(destination, 'focus');
$('.block-tree').trigger(
$.Event('keydown', {
keyCode,
target: current,
}),
);
current.dispatchEvent(new KeyboardEvent('keydown', { key }));
};
beforeEach(() => {
loadFixtures('course_experience/fixtures/course-outline-fragment.html');
new CourseOutline('.block-tree');
outline = new CourseOutline();
});
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];
const current = document.querySelector(outlineIds.homeworkLabsAndDemos);
const destination = document.querySelector(outlineIds.homeworkEssays);
triggerKeyListener(current, destination, constants.keyCodes.down);
triggerKeyListener(current, destination, 'ArrowDown'); // @TODO: Get these from the UI Toolkit
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];
it('moves focus to the subsection list if at the top of a section', () => {
const current = document.querySelector(outlineIds.exampleWeek3BeSocial);
const destination = document.querySelector(`${outlineIds.exampleWeek3BeSocial} > ol`);
triggerKeyListener(current, destination, constants.keyCodes.down);
triggerKeyListener(current, destination, 'ArrowDown'); // @TODO: Get these from the UI Toolkit
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];
const current = document.querySelector(outlineIds.homeworkEssays);
const destination = document.querySelector(outlineIds.exampleWeek3BeSocial);
triggerKeyListener(current, destination, constants.keyCodes.down);
triggerKeyListener(current, destination, 'ArrowDown'); // @TODO: Get these from the UI Toolkit
expect(destination.focus).toHaveBeenCalled();
});
......@@ -52,53 +66,48 @@ describe('Course outline factory', () => {
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];
const current = document.querySelector(outlineIds.homeworkEssays);
const destination = document.querySelector(outlineIds.homeworkLabsAndDemos);
triggerKeyListener(current, destination, constants.keyCodes.up);
triggerKeyListener(current, destination, 'ArrowUp'); // @TODO: Get these from the UI Toolkit
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];
it('moves focus to the section list if at the first subsection', () => {
const current = document.querySelector(outlineIds.lesson3BeSocial);
const destination = document.querySelector(`${outlineIds.exampleWeek3BeSocial} > ol`);
triggerKeyListener(current, destination, constants.keyCodes.up);
triggerKeyListener(current, destination, 'ArrowUp'); // @TODO: Get these from the UI Toolkit
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];
const current = document.querySelector(outlineIds.exampleWeek3BeSocial);
const destination = document.querySelector(outlineIds.homeworkEssays);
triggerKeyListener(current, destination, constants.keyCodes.up);
triggerKeyListener(current, destination, 'ArrowUp'); // @TODO: Get these from the UI Toolkit
expect(destination.focus).toHaveBeenCalled();
});
});
});
describe("eventing", function() {
beforeEach(function() {
loadFixtures("course_experience/fixtures/course-outline-fragment.html");
CourseOutlineFactory(".block-tree");
spyOn(Logger, "log");
describe('eventing', () => {
beforeEach(() => {
loadFixtures('course_experience/fixtures/course-outline-fragment.html');
outline = new CourseOutline();
spyOn(Logger, 'log');
});
it("sends an event when an outline section is clicked", function() {
$('a.focusable:contains("Homework - Labs and Demos")').click();
it('sends an event when an outline section is clicked', () => {
document.querySelector(outlineIds.homeworkLabsAndDemos).dispatchEvent(new Event('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()
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(),
});
});
});
});
......@@ -161,5 +161,5 @@ from openedx.core.djangolib.markup import HTML, Text
</%static:require_module_async>
<%static:webpack entry="CourseOutline">
new CourseOutline('.block-tree');
new CourseOutline();
</%static:webpack>
const path = require('path');
const webpack = require('webpack');
const BundleTracker = require('webpack-bundle-tracker');
const isProd = process.env.NODE_ENV === 'production';
const wpconfig = {
context: __dirname,
entry: {
CourseOutline: './openedx/features/course_experience/static/course_experience/js/CourseOutline.js',
},
output: {
path: path.resolve(__dirname, 'common/static/bundles'),
filename: '[name]-[hash].js',
libraryTarget: 'window',
},
devtool: isProd ? false : 'cheap-eval-source-map',
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
}),
new webpack.LoaderOptionsPlugin({
debug: !isProd,
}),
new BundleTracker({
filename: './webpack-stats.json'
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var isProd = process.env.NODE_ENV === 'production';
var wpconfig = {
context: __dirname,
entry: {
CourseOutline: './openedx/features/course_experience/static/course_experience/js/CourseOutline.js'
},
output: {
path: path.resolve(__dirname, 'common/static/bundles'),
filename: '[name]-[hash].js',
libraryTarget: 'window'
},
devtool: isProd ? false : 'eval-source-map',
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
new webpack.LoaderOptionsPlugin({
debug: !isProd
}),
new BundleTracker({
filename: './webpack-stats.json'
})
],
},
resolve: {
extensions: ['.js', '.json'],
}
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
},
resolve: {
extensions: ['.js', '.json']
}
};
if (isProd) {
wpconfig.plugins = [
new webpack.LoaderOptionsPlugin({
minimize: true,
}),
new webpack.optimize.UglifyJsPlugin(),
...wpconfig.plugins,
];
wpconfig.plugins = wpconfig.plugins.concat([
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new webpack.optimize.UglifyJsPlugin()
]);
}
module.exports = wpconfig;
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