Commit 89194892 by Prem Sichanugrist

Move CoffeeScripts to asset pipeline

parent 60094a17
...@@ -20,6 +20,7 @@ Longer TODO: ...@@ -20,6 +20,7 @@ Longer TODO:
""" """
import sys import sys
import tempfile import tempfile
import glob2
import djcelery import djcelery
from path import path from path import path
...@@ -285,13 +286,12 @@ PIPELINE_CSS = { ...@@ -285,13 +286,12 @@ PIPELINE_CSS = {
PIPELINE_JS = { PIPELINE_JS = {
'application': { 'application': {
'source_filenames': [ 'source_filenames': [path.replace('static/', '') for path in glob2.glob('static/coffee/src/**/*.coffee')],
'coffee/src/calculator.coffee',
'coffee/src/courseware.coffee',
'coffee/src/feedback_form.coffee',
'coffee/src/main.coffee'
],
'output_filename': 'js/application.js' 'output_filename': 'js/application.js'
},
'spec': {
'source_filenames': [path.replace('static/', '') for path in glob2.glob('static/coffee/spec/**/*.coffee')],
'output_filename': 'js/spec.js'
} }
} }
......
...@@ -21,3 +21,4 @@ django-jasmine ...@@ -21,3 +21,4 @@ django-jasmine
beautifulsoup beautifulsoup
requests requests
newrelic newrelic
glob2
(function() {
describe('Calculator', function() {
beforeEach(function() {
loadFixtures('calculator.html');
return this.calculator = new Calculator;
});
describe('bind', function() {
beforeEach(function() {
return Calculator.bind();
});
it('bind the calculator button', function() {
return expect($('.calc')).toHandleWith('click', this.calculator.toggle);
});
it('bind the help button', function() {
expect($('div.help-wrapper a')).toHandleWith('mouseenter', this.calculator.helpToggle);
return expect($('div.help-wrapper a')).toHandleWith('mouseleave', this.calculator.helpToggle);
});
it('prevent default behavior on help button', function() {
$('div.help-wrapper a').click(function(e) {
return expect(e.isDefaultPrevented()).toBeTruthy();
});
return $('div.help-wrapper a').click();
});
it('bind the calculator submit', function() {
return expect($('form#calculator')).toHandleWith('submit', this.calculator.calculate);
});
return it('prevent default behavior on form submit', function() {
jasmine.stubRequests();
$('form#calculator').submit(function(e) {
expect(e.isDefaultPrevented()).toBeTruthy();
return e.preventDefault();
});
return $('form#calculator').submit();
});
});
describe('toggle', function() {
it('toggle the calculator and focus the input', function() {
spyOn($.fn, 'focus');
this.calculator.toggle();
expect($('li.calc-main')).toHaveClass('open');
return expect($('#calculator_wrapper #calculator_input').focus).toHaveBeenCalled();
});
return it('toggle the close button on the calculator button', function() {
this.calculator.toggle();
expect($('.calc')).toHaveClass('closed');
this.calculator.toggle();
return expect($('.calc')).not.toHaveClass('closed');
});
});
describe('helpToggle', function() {
return it('toggle the help overlay', function() {
this.calculator.helpToggle();
expect($('.help')).toHaveClass('shown');
this.calculator.helpToggle();
return expect($('.help')).not.toHaveClass('shown');
});
});
return describe('calculate', function() {
beforeEach(function() {
$('#calculator_input').val('1+2');
spyOn($, 'getWithPrefix').andCallFake(function(url, data, callback) {
return callback({
result: 3
});
});
return this.calculator.calculate();
});
it('send data to /calculate', function() {
return expect($.getWithPrefix).toHaveBeenCalledWith('/calculate', {
equation: '1+2'
}, jasmine.any(Function));
});
return it('update the calculator output', function() {
return expect($('#calculator_output').val()).toEqual('3');
});
});
});
}).call(this);
(function() {
describe('Courseware', function() {
describe('start', function() {
it('create the navigation', function() {
spyOn(window, 'Navigation');
Courseware.start();
return expect(window.Navigation).toHaveBeenCalled();
});
it('create the calculator', function() {
spyOn(window, 'Calculator');
Courseware.start();
return expect(window.Calculator).toHaveBeenCalled();
});
it('creates the FeedbackForm', function() {
spyOn(window, 'FeedbackForm');
Courseware.start();
return expect(window.FeedbackForm).toHaveBeenCalled();
});
return it('binds the Logger', function() {
spyOn(Logger, 'bind');
Courseware.start();
return expect(Logger.bind).toHaveBeenCalled();
});
});
describe('bind', function() {
beforeEach(function() {
this.courseware = new Courseware;
return setFixtures("<div class=\"course-content\">\n <div class=\"sequence\"></div>\n</div>");
});
return it('binds the content change event', function() {
this.courseware.bind();
return expect($('.course-content .sequence')).toHandleWith('contentChanged', this.courseware.render);
});
});
return describe('render', function() {
beforeEach(function() {
jasmine.stubRequests();
this.courseware = new Courseware;
spyOn(window, 'Histogram');
spyOn(window, 'Problem');
spyOn(window, 'Video');
setFixtures("<div class=\"course-content\">\n <div id=\"video_1\" class=\"video\" data-streams=\"1.0:abc1234\"></div>\n <div id=\"video_2\" class=\"video\" data-streams=\"1.0:def5678\"></div>\n <div id=\"problem_3\" class=\"problems-wrapper\" data-url=\"/example/url/\">\n <div id=\"histogram_3\" class=\"histogram\" data-histogram=\"[[0, 1]]\" style=\"height: 20px; display: block;\">\n </div>\n</div>");
return this.courseware.render();
});
it('detect the video elements and convert them', function() {
expect(window.Video).toHaveBeenCalledWith('1', '1.0:abc1234');
return expect(window.Video).toHaveBeenCalledWith('2', '1.0:def5678');
});
it('detect the problem element and convert it', function() {
return expect(window.Problem).toHaveBeenCalledWith('3', '/example/url/');
});
return it('detect the histrogram element and convert it', function() {
return expect(window.Histogram).toHaveBeenCalledWith('3', [[0, 1]]);
});
});
});
}).call(this);
(function() {
describe('FeedbackForm', function() {
beforeEach(function() {
return loadFixtures('feedback_form.html');
});
return describe('constructor', function() {
beforeEach(function() {
new FeedbackForm;
return spyOn($, 'postWithPrefix').andCallFake(function(url, data, callback, format) {
return callback();
});
});
it('binds to the #feedback_button', function() {
return expect($('#feedback_button')).toHandle('click');
});
it('post data to /send_feedback on click', function() {
$('#feedback_subject').val('Awesome!');
$('#feedback_message').val('This site is really good.');
$('#feedback_button').click();
return expect($.postWithPrefix).toHaveBeenCalledWith('/send_feedback', {
subject: 'Awesome!',
message: 'This site is really good.',
url: window.location.href
}, jasmine.any(Function), 'json');
});
return it('replace the form with a thank you message', function() {
$('#feedback_button').click();
return expect($('#feedback_div').html()).toEqual('Feedback submitted. Thank you');
});
});
});
}).call(this);
(function() {
jasmine.getFixtures().fixturesPath = "/_jasmine/fixtures/";
jasmine.stubbedMetadata = {
abc123: {
id: 'abc123',
duration: 100
},
def456: {
id: 'def456',
duration: 200
},
bogus: {
duration: 300
}
};
jasmine.stubbedCaption = {
start: [0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000, 120000],
text: ['Caption at 0', 'Caption at 10000', 'Caption at 20000', 'Caption at 30000', 'Caption at 40000', 'Caption at 50000', 'Caption at 60000', 'Caption at 70000', 'Caption at 80000', 'Caption at 90000', 'Caption at 100000', 'Caption at 110000', 'Caption at 120000']
};
jasmine.stubRequests = function() {
return spyOn($, 'ajax').andCallFake(function(settings) {
var match;
if (match = settings.url.match(/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/)) {
return settings.success({
data: jasmine.stubbedMetadata[match[1]]
});
} else if (match = settings.url.match(/static\/subs\/(.+)\.srt\.sjson/)) {
return settings.success(jasmine.stubbedCaption);
} else if (settings.url === '/calculate' || settings.url === '/6002x/modx/sequential/1/goto_position' || settings.url.match(/event$/) || settings.url.match(/6002x\/modx\/problem\/.+\/problem_(check|reset|show|save)$/)) {
} else {
throw "External request attempted for " + settings.url + ", which is not defined.";
}
});
};
jasmine.stubYoutubePlayer = function() {
return YT.Player = function() {
return jasmine.createSpyObj('YT.Player', ['cueVideoById', 'getVideoEmbedCode', 'getCurrentTime', 'getPlayerState', 'loadVideoById', 'playVideo', 'pauseVideo', 'seekTo']);
};
};
jasmine.stubVideoPlayer = function(context, enableParts) {
var currentPartName, part, suite, _i, _len, _ref;
if (!$.isArray(enableParts)) {
enableParts = [enableParts];
}
suite = context.suite;
while (suite = suite.parentSuite) {
currentPartName = suite.description;
}
enableParts.push(currentPartName);
_ref = ['VideoCaption', 'VideoSpeedControl', 'VideoProgressSlider'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
part = _ref[_i];
if (!($.inArray(part, enableParts) >= 0)) {
spyOn(window, part);
}
}
loadFixtures('video.html');
jasmine.stubRequests();
YT.Player = void 0;
context.video = new Video('example', '.75:abc123,1.0:def456');
jasmine.stubYoutubePlayer();
return new VideoPlayer(context.video);
};
spyOn(window, 'onunload');
window.YT = {
PlayerState: {
UNSTARTED: -1,
ENDED: 0,
PLAYING: 1,
PAUSED: 2,
BUFFERING: 3,
CUED: 5
}
};
$.cookie = jasmine.createSpy('jQuery.cookie').andReturn('1.0');
$.fn.qtip = jasmine.createSpy('jQuery.qtip');
$.fn.scrollTo = jasmine.createSpy('jQuery.scrollTo');
}).call(this);
...@@ -9,6 +9,7 @@ describe 'Video', -> ...@@ -9,6 +9,7 @@ describe 'Video', ->
describe 'constructor', -> describe 'constructor', ->
beforeEach -> beforeEach ->
@stubVideoPlayer = jasmine.createSpy('VideoPlayer')
$.cookie.andReturn '0.75' $.cookie.andReturn '0.75'
window.player = 100 window.player = 100
...@@ -49,7 +50,6 @@ describe 'Video', -> ...@@ -49,7 +50,6 @@ describe 'Video', ->
beforeEach -> beforeEach ->
@originalYT = window.YT @originalYT = window.YT
window.YT = { Player: true } window.YT = { Player: true }
@stubVideoPlayer = jasmine.createSpy('VideoPlayer')
spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer) spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer)
@video = new Video 'example', '.75:abc123,1.0:def456' @video = new Video 'example', '.75:abc123,1.0:def456'
...@@ -62,18 +62,27 @@ describe 'Video', -> ...@@ -62,18 +62,27 @@ describe 'Video', ->
describe 'when the Youtube API is not ready', -> describe 'when the Youtube API is not ready', ->
beforeEach -> beforeEach ->
@originalYT = window.YT
window.YT = {}
@video = new Video 'example', '.75:abc123,1.0:def456' @video = new Video 'example', '.75:abc123,1.0:def456'
afterEach ->
window.YT = @originalYT
it 'set the callback on the window object', -> it 'set the callback on the window object', ->
expect(window.onYouTubePlayerAPIReady).toEqual jasmine.any(Function) expect(window.onYouTubePlayerAPIReady).toEqual jasmine.any(Function)
describe 'when the Youtube API becoming ready', -> describe 'when the Youtube API becoming ready', ->
beforeEach -> beforeEach ->
@stubVideoPlayer = jasmine.createSpy('VideoPlayer') @originalYT = window.YT
window.YT = {}
spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer) spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer)
@video = new Video 'example', '.75:abc123,1.0:def456' @video = new Video 'example', '.75:abc123,1.0:def456'
window.onYouTubePlayerAPIReady() window.onYouTubePlayerAPIReady()
afterEach ->
window.YT = @originalYT
it 'create the Video Player for all video elements', -> it 'create the Video Player for all video elements', ->
expect(window.VideoPlayer).toHaveBeenCalledWith @video expect(window.VideoPlayer).toHaveBeenCalledWith @video
expect(@video.player).toEqual @stubVideoPlayer expect(@video.player).toEqual @stubVideoPlayer
......
...@@ -184,7 +184,18 @@ section.course-content { ...@@ -184,7 +184,18 @@ section.course-content {
float: left; float: left;
position: relative; position: relative;
a { &.open {
&>a {
background: url('../images/open-arrow.png') 10px center no-repeat;
}
ol.video_speeds {
display: block;
opacity: 1;
}
}
&>a {
background: url('../images/closed-arrow.png') 10px center no-repeat; background: url('../images/closed-arrow.png') 10px center no-repeat;
border-left: 1px solid #000; border-left: 1px solid #000;
border-right: 1px solid #000; border-right: 1px solid #000;
...@@ -201,15 +212,6 @@ section.course-content { ...@@ -201,15 +212,6 @@ section.course-content {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
width: 110px; width: 110px;
&.open {
background: url('../images/open-arrow.png') 10px center no-repeat;
ol.video_speeds {
display: block;
opacity: 1;
}
}
h3 { h3 {
color: #999; color: #999;
float: left; float: left;
......
(function() {
describe('Histogram', function() {
beforeEach(function() {
return spyOn($, 'plot');
});
describe('constructor', function() {
return it('instantiate the data arrays', function() {
var histogram;
histogram = new Histogram(1, []);
expect(histogram.xTicks).toEqual([]);
expect(histogram.yTicks).toEqual([]);
return expect(histogram.data).toEqual([]);
});
});
describe('calculate', function() {
beforeEach(function() {
return this.histogram = new Histogram(1, [[1, 1], [2, 2], [3, 3]]);
});
it('store the correct value for data', function() {
return expect(this.histogram.data).toEqual([[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]]);
});
it('store the correct value for x ticks', function() {
return expect(this.histogram.xTicks).toEqual([[1, '1'], [2, '2'], [3, '3']]);
});
return it('store the correct value for y ticks', function() {
return expect(this.histogram.yTicks).toEqual;
});
});
return describe('render', function() {
return it('call flot with correct option', function() {
new Histogram(1, [[1, 1], [2, 2], [3, 3]]);
return expect($.plot).toHaveBeenCalledWith($("#histogram_1"), [
{
data: [[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]],
bars: {
show: true,
align: 'center',
lineWidth: 0,
fill: 1.0
},
color: "#b72121"
}
], {
xaxis: {
min: -1,
max: 4,
ticks: [[1, '1'], [2, '2'], [3, '3']],
tickLength: 0
},
yaxis: {
min: 0.0,
max: Math.log(4) * 1.1,
ticks: [[Math.log(2), '1'], [Math.log(3), '2'], [Math.log(4), '3']],
labelWidth: 50
}
});
});
});
});
}).call(this);
(function() {
describe('Logger', function() {
it('expose window.log_event', function() {
jasmine.stubRequests();
return expect(window.log_event).toBe(Logger.log);
});
describe('log', function() {
return it('send a request to log event', function() {
spyOn($, 'getWithPrefix');
Logger.log('example', 'data');
return expect($.getWithPrefix).toHaveBeenCalledWith('/event', {
event_type: 'example',
event: '"data"',
page: window.location.href
});
});
});
return describe('bind', function() {
beforeEach(function() {
Logger.bind();
return Courseware.prefix = '/6002x';
});
afterEach(function() {
return window.onunload = null;
});
it('bind the onunload event', function() {
return expect(window.onunload).toEqual(jasmine.any(Function));
});
return it('send a request to log event', function() {
spyOn($, 'ajax');
$(window).trigger('onunload');
return expect($.ajax).toHaveBeenCalledWith({
url: "" + Courseware.prefix + "/event",
data: {
event_type: 'page_close',
event: '',
page: window.location.href
},
async: false
});
});
});
});
}).call(this);
(function() {
describe('Problem', function() {
beforeEach(function() {
window.MathJax = {
Hub: {
Queue: function() {}
}
};
window.update_schematics = function() {};
loadFixtures('problem.html');
spyOn(Logger, 'log');
return spyOn($.fn, 'load').andCallFake(function(url, callback) {
$(this).html(readFixtures('problem_content.html'));
return callback();
});
});
describe('constructor', function() {
beforeEach(function() {
return this.problem = new Problem(1, '/problem/url/');
});
it('set the element', function() {
return expect(this.problem.element).toBe('#problem_1');
});
it('set the content url', function() {
return expect(this.problem.content_url).toEqual('/problem/url/problem_get?id=1');
});
return it('render the content', function() {
return expect($.fn.load).toHaveBeenCalledWith(this.problem.content_url, this.problem.bind);
});
});
describe('bind', function() {
beforeEach(function() {
spyOn(MathJax.Hub, 'Queue');
spyOn(window, 'update_schematics');
return this.problem = new Problem(1, '/problem/url/');
});
it('set mathjax typeset', function() {
return expect(MathJax.Hub.Queue).toHaveBeenCalled();
});
it('update schematics', function() {
return expect(window.update_schematics).toHaveBeenCalled();
});
it('bind answer refresh on button click', function() {
return expect($('section.action input:button')).toHandleWith('click', this.problem.refreshAnswers);
});
it('bind the check button', function() {
return expect($('section.action input.check')).toHandleWith('click', this.problem.check);
});
it('bind the reset button', function() {
return expect($('section.action input.reset')).toHandleWith('click', this.problem.reset);
});
it('bind the show button', function() {
return expect($('section.action input.show')).toHandleWith('click', this.problem.show);
});
return it('bind the save button', function() {
return expect($('section.action input.save')).toHandleWith('click', this.problem.save);
});
});
describe('render', function() {
beforeEach(function() {
this.problem = new Problem(1, '/problem/url/');
this.bind = this.problem.bind;
return spyOn(this.problem, 'bind');
});
describe('with content given', function() {
beforeEach(function() {
return this.problem.render('Hello World');
});
it('render the content', function() {
return expect(this.problem.element.html()).toEqual('Hello World');
});
return it('re-bind the content', function() {
return expect(this.problem.bind).toHaveBeenCalled();
});
});
return describe('with no content given', function() {
return it('load the content via ajax', function() {
return expect($.fn.load).toHaveBeenCalledWith(this.problem.content_url, this.bind);
});
});
});
describe('check', function() {
beforeEach(function() {
jasmine.stubRequests();
this.problem = new Problem(1, '/problem/url/');
return this.problem.answers = 'foo=1&bar=2';
});
it('log the problem_check event', function() {
this.problem.check();
return expect(Logger.log).toHaveBeenCalledWith('problem_check', 'foo=1&bar=2');
});
it('submit the answer for check', function() {
spyOn($, 'postWithPrefix');
this.problem.check();
return expect($.postWithPrefix).toHaveBeenCalledWith('/modx/problem/1/problem_check', 'foo=1&bar=2', jasmine.any(Function));
});
describe('when the response is correct', function() {
return it('call render with returned content', function() {
spyOn($, 'postWithPrefix').andCallFake(function(url, answers, callback) {
return callback({
success: 'correct',
contents: 'Correct!'
});
});
this.problem.check();
return expect(this.problem.element.html()).toEqual('Correct!');
});
});
describe('when the response is incorrect', function() {
return it('call render with returned content', function() {
spyOn($, 'postWithPrefix').andCallFake(function(url, answers, callback) {
return callback({
success: 'incorrect',
contents: 'Correct!'
});
});
this.problem.check();
return expect(this.problem.element.html()).toEqual('Correct!');
});
});
return describe('when the response is undetermined', function() {
return it('alert the response', function() {
spyOn(window, 'alert');
spyOn($, 'postWithPrefix').andCallFake(function(url, answers, callback) {
return callback({
success: 'Number Only!'
});
});
this.problem.check();
return expect(window.alert).toHaveBeenCalledWith('Number Only!');
});
});
});
describe('reset', function() {
beforeEach(function() {
jasmine.stubRequests();
return this.problem = new Problem(1, '/problem/url/');
});
it('log the problem_reset event', function() {
this.problem.answers = 'foo=1&bar=2';
this.problem.reset();
return expect(Logger.log).toHaveBeenCalledWith('problem_reset', 'foo=1&bar=2');
});
it('POST to the problem reset page', function() {
spyOn($, 'postWithPrefix');
this.problem.reset();
return expect($.postWithPrefix).toHaveBeenCalledWith('/modx/problem/1/problem_reset', {
id: 1
}, jasmine.any(Function));
});
return it('render the returned content', function() {
spyOn($, 'postWithPrefix').andCallFake(function(url, answers, callback) {
return callback("Reset!");
});
this.problem.reset();
return expect(this.problem.element.html()).toEqual('Reset!');
});
});
describe('show', function() {
beforeEach(function() {
jasmine.stubRequests();
this.problem = new Problem(1, '/problem/url/');
return this.problem.element.prepend('<div id="answer_1_1" /><div id="answer_1_2" />');
});
describe('when the answer has not yet shown', function() {
beforeEach(function() {
return this.problem.element.removeClass('showed');
});
it('log the problem_show event', function() {
this.problem.show();
return expect(Logger.log).toHaveBeenCalledWith('problem_show', {
problem: 1
});
});
it('fetch the answers', function() {
spyOn($, 'postWithPrefix');
this.problem.show();
return expect($.postWithPrefix).toHaveBeenCalledWith('/modx/problem/1/problem_show', jasmine.any(Function));
});
it('show the answers', function() {
spyOn($, 'postWithPrefix').andCallFake(function(url, callback) {
return callback({
'1_1': 'One',
'1_2': 'Two'
});
});
this.problem.show();
expect($('#answer_1_1')).toHaveHtml('One');
return expect($('#answer_1_2')).toHaveHtml('Two');
});
it('toggle the show answer button', function() {
spyOn($, 'postWithPrefix').andCallFake(function(url, callback) {
return callback({});
});
this.problem.show();
return expect($('.show')).toHaveValue('Hide Answer');
});
it('add the showed class to element', function() {
spyOn($, 'postWithPrefix').andCallFake(function(url, callback) {
return callback({});
});
this.problem.show();
return expect(this.problem.element).toHaveClass('showed');
});
return describe('multiple choice question', function() {
beforeEach(function() {
return this.problem.element.prepend('<label for="input_1_1_1"><input type="checkbox" name="input_1_1" id="input_1_1_1" value="1"> One</label>\n<label for="input_1_1_2"><input type="checkbox" name="input_1_1" id="input_1_1_2" value="2"> Two</label>\n<label for="input_1_1_3"><input type="checkbox" name="input_1_1" id="input_1_1_3" value="3"> Three</label>\n<label for="input_1_2_1"><input type="radio" name="input_1_2" id="input_1_2_1" value="1"> Other</label>');
});
return it('set the correct_answer attribute on the choice', function() {
spyOn($, 'postWithPrefix').andCallFake(function(url, callback) {
return callback({
'1_1': [2, 3]
});
});
this.problem.show();
expect($('label[for="input_1_1_1"]')).not.toHaveAttr('correct_answer', 'true');
expect($('label[for="input_1_1_2"]')).toHaveAttr('correct_answer', 'true');
expect($('label[for="input_1_1_3"]')).toHaveAttr('correct_answer', 'true');
return expect($('label[for="input_1_2_1"]')).not.toHaveAttr('correct_answer', 'true');
});
});
});
return describe('when the answers are alreay shown', function() {
beforeEach(function() {
this.problem.element.addClass('showed');
this.problem.element.prepend('<label for="input_1_1_1" correct_answer="true">\n <input type="checkbox" name="input_1_1" id="input_1_1_1" value="1" />\n One\n</label>');
$('#answer_1_1').html('One');
return $('#answer_1_2').html('Two');
});
it('hide the answers', function() {
this.problem.show();
expect($('#answer_1_1')).toHaveHtml('');
expect($('#answer_1_2')).toHaveHtml('');
return expect($('label[for="input_1_1_1"]')).not.toHaveAttr('correct_answer');
});
it('toggle the show answer button', function() {
this.problem.show();
return expect($('.show')).toHaveValue('Show Answer');
});
return it('remove the showed class from element', function() {
this.problem.show();
return expect(this.problem.element).not.toHaveClass('showed');
});
});
});
describe('save', function() {
beforeEach(function() {
jasmine.stubRequests();
this.problem = new Problem(1, '/problem/url/');
return this.problem.answers = 'foo=1&bar=2';
});
it('log the problem_save event', function() {
this.problem.save();
return expect(Logger.log).toHaveBeenCalledWith('problem_save', 'foo=1&bar=2');
});
it('POST to save problem', function() {
spyOn($, 'postWithPrefix');
this.problem.save();
return expect($.postWithPrefix).toHaveBeenCalledWith('/modx/problem/1/problem_save', 'foo=1&bar=2', jasmine.any(Function));
});
return it('alert to the user', function() {
spyOn(window, 'alert');
spyOn($, 'postWithPrefix').andCallFake(function(url, answers, callback) {
return callback({
success: 'OK'
});
});
this.problem.save();
return expect(window.alert).toHaveBeenCalledWith('Saved');
});
});
return describe('refreshAnswers', function() {
beforeEach(function() {
this.problem = new Problem(1, '/problem/url/');
this.problem.element.html('<textarea class="CodeMirror" />\n<input id="input_1_1" name="input_1_1" class="schematic" value="one" />\n<input id="input_1_2" name="input_1_2" value="two" />\n<input id="input_bogus_3" name="input_bogus_3" value="three" />');
this.stubSchematic = {
update_value: jasmine.createSpy('schematic')
};
this.stubCodeMirror = {
save: jasmine.createSpy('CodeMirror')
};
$('input.schematic').get(0).schematic = this.stubSchematic;
return $('textarea.CodeMirror').get(0).CodeMirror = this.stubCodeMirror;
});
it('update each schematic', function() {
this.problem.refreshAnswers();
return expect(this.stubSchematic.update_value).toHaveBeenCalled();
});
it('update each code block', function() {
this.problem.refreshAnswers();
return expect(this.stubCodeMirror.save).toHaveBeenCalled();
});
return it('serialize all answers', function() {
this.problem.refreshAnswers();
return expect(this.problem.answers).toEqual("input_1_1=one&input_1_2=two");
});
});
});
}).call(this);
(function() {
describe('Sequence', function() {
beforeEach(function() {
window.MathJax = {
Hub: {
Queue: function() {}
}
};
spyOn(Logger, 'log');
loadFixtures('sequence.html');
return this.items = $.parseJSON(readFixtures('items.json'));
});
describe('constructor', function() {
beforeEach(function() {
return this.sequence = new Sequence('1', this.items, 1);
});
it('set the element', function() {
return expect(this.sequence.element).toEqual($('#sequence_1'));
});
it('build the navigation', function() {
var classes, elements, titles;
classes = $('#sequence-list li>a').map(function() {
return $(this).attr('class');
}).get();
elements = $('#sequence-list li>a').map(function() {
return $(this).attr('data-element');
}).get();
titles = $('#sequence-list li>a>p').map(function() {
return $(this).html();
}).get();
expect(classes).toEqual(['seq_video_active', 'seq_video_inactive', 'seq_problem_inactive']);
expect(elements).toEqual(['1', '2', '3']);
return expect(titles).toEqual(['Video 1', 'Video 2', 'Sample Problem']);
});
it('bind the page events', function() {
expect(this.sequence.element).toHandleWith('contentChanged', this.sequence.toggleArrows);
return expect($('#sequence-list a')).toHandleWith('click', this.sequence.goto);
});
return it('render the active sequence content', function() {
return expect($('#seq_content').html()).toEqual('Video 1');
});
});
describe('toggleArrows', function() {
beforeEach(function() {
return this.sequence = new Sequence('1', this.items, 1);
});
describe('when the first tab is active', function() {
beforeEach(function() {
this.sequence.position = 1;
return this.sequence.toggleArrows();
});
it('disable the previous button', function() {
return expect($('.sequence-nav-buttons .prev a')).toHaveClass('disabled');
});
return it('enable the next button', function() {
expect($('.sequence-nav-buttons .next a')).not.toHaveClass('disabled');
return expect($('.sequence-nav-buttons .next a')).toHandleWith('click', this.sequence.next);
});
});
describe('when the middle tab is active', function() {
beforeEach(function() {
this.sequence.position = 2;
return this.sequence.toggleArrows();
});
it('enable the previous button', function() {
expect($('.sequence-nav-buttons .prev a')).not.toHaveClass('disabled');
return expect($('.sequence-nav-buttons .prev a')).toHandleWith('click', this.sequence.previous);
});
return it('enable the next button', function() {
expect($('.sequence-nav-buttons .next a')).not.toHaveClass('disabled');
return expect($('.sequence-nav-buttons .next a')).toHandleWith('click', this.sequence.next);
});
});
return describe('when the last tab is active', function() {
beforeEach(function() {
this.sequence.position = 3;
return this.sequence.toggleArrows();
});
it('enable the previous button', function() {
expect($('.sequence-nav-buttons .prev a')).not.toHaveClass('disabled');
return expect($('.sequence-nav-buttons .prev a')).toHandleWith('click', this.sequence.previous);
});
return it('disable the next button', function() {
return expect($('.sequence-nav-buttons .next a')).toHaveClass('disabled');
});
});
});
describe('render', function() {
beforeEach(function() {
spyOn($, 'postWithPrefix');
this.sequence = new Sequence('1', this.items);
return spyOnEvent(this.sequence.element, 'contentChanged');
});
describe('with a different position than the current one', function() {
beforeEach(function() {
return this.sequence.render(1);
});
describe('with no previous position', function() {
return it('does not save the new position', function() {
return expect($.postWithPrefix).not.toHaveBeenCalled();
});
});
describe('with previous position', function() {
beforeEach(function() {
this.sequence.position = 2;
return this.sequence.render(1);
});
it('mark the previous tab as visited', function() {
return expect($('[data-element="2"]')).toHaveClass('seq_video_visited');
});
return it('save the new position', function() {
return expect($.postWithPrefix).toHaveBeenCalledWith('/modx/sequential/1/goto_position', {
position: 1
});
});
});
it('mark new tab as active', function() {
return expect($('[data-element="1"]')).toHaveClass('seq_video_active');
});
it('render the new content', function() {
return expect($('#seq_content').html()).toEqual('Video 1');
});
it('update the position', function() {
return expect(this.sequence.position).toEqual(1);
});
return it('trigger contentChanged event', function() {
return expect('contentChanged').toHaveBeenTriggeredOn(this.sequence.element);
});
});
return describe('with the same position as the current one', function() {
return it('should not trigger contentChanged event', function() {
this.sequence.position = 2;
this.sequence.render(2);
return expect('contentChanged').not.toHaveBeenTriggeredOn(this.sequence.element);
});
});
});
describe('goto', function() {
beforeEach(function() {
jasmine.stubRequests();
this.sequence = new Sequence('1', this.items, 2);
return $('[data-element="3"]').click();
});
it('log the sequence goto event', function() {
return expect(Logger.log).toHaveBeenCalledWith('seq_goto', {
old: 2,
"new": 3,
id: '1'
});
});
return it('call render on the right sequence', function() {
return expect($('#seq_content').html()).toEqual('Sample Problem');
});
});
describe('next', function() {
beforeEach(function() {
jasmine.stubRequests();
this.sequence = new Sequence('1', this.items, 2);
return $('.sequence-nav-buttons .next a').click();
});
it('log the next sequence event', function() {
return expect(Logger.log).toHaveBeenCalledWith('seq_next', {
old: 2,
"new": 3,
id: '1'
});
});
return it('call render on the next sequence', function() {
return expect($('#seq_content').html()).toEqual('Sample Problem');
});
});
describe('previous', function() {
beforeEach(function() {
jasmine.stubRequests();
this.sequence = new Sequence('1', this.items, 2);
return $('.sequence-nav-buttons .prev a').click();
});
it('log the previous sequence event', function() {
return expect(Logger.log).toHaveBeenCalledWith('seq_prev', {
old: 2,
"new": 1,
id: '1'
});
});
return it('call render on the previous sequence', function() {
return expect($('#seq_content').html()).toEqual('Video 1');
});
});
return describe('link_for', function() {
return it('return a link for specific position', function() {
var sequence;
sequence = new Sequence('1', this.items, 2);
return expect(sequence.link_for(2)).toBe('[data-element="2"]');
});
});
});
}).call(this);
(function() {
describe('Tab', function() {
beforeEach(function() {
loadFixtures('tab.html');
return this.items = $.parseJSON(readFixtures('items.json'));
});
describe('constructor', function() {
beforeEach(function() {
spyOn($.fn, 'tabs');
return this.tab = new Tab(1, this.items);
});
it('set the element', function() {
return expect(this.tab.element).toEqual($('#tab_1'));
});
it('build the tabs', function() {
var links;
links = $('.navigation li>a').map(function() {
return $(this).attr('href');
}).get();
return expect(links).toEqual(['#tab-1-0', '#tab-1-1', '#tab-1-2']);
});
it('build the container', function() {
var containers;
containers = $('section').map(function() {
return $(this).attr('id');
}).get();
return expect(containers).toEqual(['tab-1-0', 'tab-1-1', 'tab-1-2']);
});
return it('bind the tabs', function() {
return expect($.fn.tabs).toHaveBeenCalledWith({
show: this.tab.onShow
});
});
});
return describe('onShow', function() {
beforeEach(function() {
this.tab = new Tab(1, this.items);
return $('[href="#tab-1-0"]').click();
});
it('replace content in the container', function() {
$('[href="#tab-1-1"]').click();
expect($('#tab-1-0').html()).toEqual('');
expect($('#tab-1-1').html()).toEqual('Video 2');
return expect($('#tab-1-2').html()).toEqual('');
});
return it('trigger contentChanged event on the element', function() {
spyOnEvent(this.tab.element, 'contentChanged');
$('[href="#tab-1-1"]').click();
return expect('contentChanged').toHaveBeenTriggeredOn(this.tab.element);
});
});
});
}).call(this);
(function() {
describe('VideoCaption', function() {
beforeEach(function() {
return this.player = jasmine.stubVideoPlayer(this);
});
afterEach(function() {
YT.Player = void 0;
return $.fn.scrollTo.reset();
});
describe('constructor', function() {
beforeEach(function() {
spyOn($, 'getWithPrefix').andCallThrough();
return this.caption = new VideoCaption(this.player, 'def456');
});
it('set the player', function() {
return expect(this.caption.player).toEqual(this.player);
});
it('set the youtube id', function() {
return expect(this.caption.youtubeId).toEqual('def456');
});
it('create the caption element', function() {
return expect($('.video')).toContain('ol.subtitles');
});
it('add caption control to video player', function() {
return expect($('.video')).toContain('a.hide-subtitles');
});
it('fetch the caption', function() {
return expect($.getWithPrefix).toHaveBeenCalledWith(this.caption.captionURL(), jasmine.any(Function));
});
it('render the caption', function() {
return expect($('.subtitles').html()).toMatch(new RegExp('<li data-index="0" data-start="0">Caption at 0</li>\n<li data-index="1" data-start="10000">Caption at 10000</li>\n<li data-index="2" data-start="20000">Caption at 20000</li>\n<li data-index="3" data-start="30000">Caption at 30000</li>\n<li data-index="4" data-start="40000">Caption at 40000</li>\n<li data-index="5" data-start="50000">Caption at 50000</li>\n<li data-index="6" data-start="60000">Caption at 60000</li>\n<li data-index="7" data-start="70000">Caption at 70000</li>\n<li data-index="8" data-start="80000">Caption at 80000</li>\n<li data-index="9" data-start="90000">Caption at 90000</li>\n<li data-index="10" data-start="100000">Caption at 100000</li>\n<li data-index="11" data-start="110000">Caption at 110000</li>\n<li data-index="12" data-start="120000">Caption at 120000</li>'.replace(/\n/g, '')));
});
it('add a padding element to caption', function() {
expect($('.subtitles li:first')).toBe('.spacing');
return expect($('.subtitles li:last')).toBe('.spacing');
});
it('bind all the caption link', function() {
var _this = this;
return $('.subtitles li[data-index]').each(function(index, link) {
return expect($(link)).toHandleWith('click', _this.caption.seekPlayer);
});
});
it('bind window resize event', function() {
return expect($(window)).toHandleWith('resize', this.caption.onWindowResize);
});
it('bind player resize event', function() {
return expect($(this.player)).toHandleWith('resize', this.caption.onWindowResize);
});
it('bind player updatePlayTime event', function() {
return expect($(this.player)).toHandleWith('updatePlayTime', this.caption.onUpdatePlayTime);
});
it('bind the hide caption button', function() {
return expect($('.hide-subtitles')).toHandleWith('click', this.caption.toggle);
});
return it('bind the mouse movement', function() {
expect($('.subtitles')).toHandleWith('mouseenter', this.caption.onMouseEnter);
expect($('.subtitles')).toHandleWith('mouseleave', this.caption.onMouseLeave);
expect($('.subtitles')).toHandleWith('mousemove', this.caption.onMovement);
expect($('.subtitles')).toHandleWith('mousewheel', this.caption.onMovement);
return expect($('.subtitles')).toHandleWith('DOMMouseScroll', this.caption.onMovement);
});
});
describe('mouse movement', function() {
beforeEach(function() {
spyOn(window, 'setTimeout').andReturn(100);
spyOn(window, 'clearTimeout');
return this.caption = new VideoCaption(this.player, 'def456');
});
describe('when cursor is outside of the caption box', function() {
beforeEach(function() {
return $(window).trigger(jQuery.Event('mousemove'));
});
return it('does not set freezing timeout', function() {
return expect(this.caption.frozen).toBeFalsy();
});
});
describe('when cursor is in the caption box', function() {
beforeEach(function() {
return $('.subtitles').trigger(jQuery.Event('mouseenter'));
});
it('set the freezing timeout', function() {
return expect(this.caption.frozen).toEqual(100);
});
describe('when the cursor is moving', function() {
beforeEach(function() {
return $('.subtitles').trigger(jQuery.Event('mousemove'));
});
return it('reset the freezing timeout', function() {
return expect(window.clearTimeout).toHaveBeenCalledWith(100);
});
});
return describe('when the mouse is scrolling', function() {
beforeEach(function() {
return $('.subtitles').trigger(jQuery.Event('mousewheel'));
});
return it('reset the freezing timeout', function() {
return expect(window.clearTimeout).toHaveBeenCalledWith(100);
});
});
});
return describe('when cursor is moving out of the caption box', function() {
beforeEach(function() {
this.caption.frozen = 100;
return $.fn.scrollTo.reset();
});
describe('always', function() {
beforeEach(function() {
return $('.subtitles').trigger(jQuery.Event('mouseout'));
});
it('reset the freezing timeout', function() {
return expect(window.clearTimeout).toHaveBeenCalledWith(100);
});
return it('unfreeze the caption', function() {
return expect(this.caption.frozen).toBeNull();
});
});
describe('when the player is playing', function() {
beforeEach(function() {
spyOn(this.player, 'isPlaying').andReturn(true);
$('.subtitles li[data-index]:first').addClass('current');
return $('.subtitles').trigger(jQuery.Event('mouseout'));
});
return it('scroll the caption', function() {
return expect($.fn.scrollTo).toHaveBeenCalled();
});
});
return describe('when the player is not playing', function() {
beforeEach(function() {
spyOn(this.player, 'isPlaying').andReturn(false);
return $('.subtitles').trigger(jQuery.Event('mouseout'));
});
return it('does not scroll the caption', function() {
return expect($.fn.scrollTo).not.toHaveBeenCalled();
});
});
});
});
describe('search', function() {
beforeEach(function() {
return this.caption = new VideoCaption(this.player, 'def456');
});
return it('return a correct caption index', function() {
expect(this.caption.search(0)).toEqual(0);
expect(this.caption.search(9999)).toEqual(0);
expect(this.caption.search(10000)).toEqual(1);
expect(this.caption.search(15000)).toEqual(1);
expect(this.caption.search(120000)).toEqual(12);
return expect(this.caption.search(120001)).toEqual(12);
});
});
describe('onUpdatePlayTime', function() {
beforeEach(function() {
return this.caption = new VideoCaption(this.player, 'def456');
});
describe('when the video speed is 1.0x', function() {
beforeEach(function() {
this.video.setSpeed('1.0');
return this.caption.onUpdatePlayTime({}, 25.000);
});
return it('search the caption based on time', function() {
return expect(this.caption.currentIndex).toEqual(2);
});
});
describe('when the video speed is not 1.0x', function() {
beforeEach(function() {
this.video.setSpeed('0.75');
return this.caption.onUpdatePlayTime({}, 25.000);
});
return it('search the caption based on 1.0x speed', function() {
return expect(this.caption.currentIndex).toEqual(1);
});
});
describe('when the index is not the same', function() {
beforeEach(function() {
this.caption.currentIndex = 1;
$('.subtitles li[data-index=1]').addClass('current');
return this.caption.onUpdatePlayTime({}, 25.000);
});
it('deactivate the previous caption', function() {
return expect($('.subtitles li[data-index=1]')).not.toHaveClass('current');
});
it('activate new caption', function() {
return expect($('.subtitles li[data-index=2]')).toHaveClass('current');
});
it('save new index', function() {
return expect(this.caption.currentIndex).toEqual(2);
});
return it('scroll caption to new position', function() {
return expect($.fn.scrollTo).toHaveBeenCalled();
});
});
return describe('when the index is the same', function() {
beforeEach(function() {
this.caption.currentIndex = 1;
$('.subtitles li[data-index=1]').addClass('current');
return this.caption.onUpdatePlayTime({}, 15.000);
});
return it('does not change current subtitle', function() {
return expect($('.subtitles li[data-index=1]')).toHaveClass('current');
});
});
});
describe('onWindowResize', function() {
beforeEach(function() {
this.caption = new VideoCaption(this.player, 'def456');
$('.subtitles li[data-index=1]').addClass('current');
return this.caption.onWindowResize();
});
it('set the height of caption container', function() {
return expect(parseInt($('.subtitles').css('maxHeight'))).toEqual($('.video-wrapper').height());
});
it('set the height of caption spacing', function() {
expect(parseInt($('.subtitles .spacing:first').css('height'))).toEqual($('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):first').height() / 2);
return expect(parseInt($('.subtitles .spacing:last').css('height'))).toEqual($('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):last').height() / 2);
});
return it('scroll caption to new position', function() {
return expect($.fn.scrollTo).toHaveBeenCalled();
});
});
describe('scrollCaption', function() {
beforeEach(function() {
return this.caption = new VideoCaption(this.player, 'def456');
});
describe('when frozen', function() {
beforeEach(function() {
this.caption.frozen = true;
$('.subtitles li[data-index=1]').addClass('current');
return this.caption.scrollCaption();
});
return it('does not scroll the caption', function() {
return expect($.fn.scrollTo).not.toHaveBeenCalled();
});
});
return describe('when not frozen', function() {
beforeEach(function() {
return this.caption.frozen = false;
});
describe('when there is no current caption', function() {
beforeEach(function() {
return this.caption.scrollCaption();
});
return it('does not scroll the caption', function() {
return expect($.fn.scrollTo).not.toHaveBeenCalled();
});
});
return describe('when there is a current caption', function() {
beforeEach(function() {
$('.subtitles li[data-index=1]').addClass('current');
return this.caption.scrollCaption();
});
return it('scroll to current caption', function() {
return expect($.fn.scrollTo).toHaveBeenCalledWith($('.subtitles .current:first', this.player.element), {
offset: -($('.video-wrapper').height() / 2 - $('.subtitles .current:first').height() / 2)
});
});
});
});
});
describe('seekPlayer', function() {
beforeEach(function() {
var _this = this;
this.caption = new VideoCaption(this.player, 'def456');
this.time = null;
return $(this.player).bind('seek', function(event, time) {
return _this.time = time;
});
});
describe('when the video speed is 1.0x', function() {
beforeEach(function() {
this.video.setSpeed('1.0');
return $('.subtitles li[data-start="30000"]').click();
});
return it('trigger seek event with the correct time', function() {
return expect(this.time).toEqual(30.000);
});
});
return describe('when the video speed is not 1.0x', function() {
beforeEach(function() {
this.video.setSpeed('0.75');
return $('.subtitles li[data-start="30000"]').click();
});
return it('trigger seek event with the correct time', function() {
return expect(this.time).toEqual(40.000);
});
});
});
return describe('toggle', function() {
beforeEach(function() {
this.caption = new VideoCaption(this.player, 'def456');
return $('.subtitles li[data-index=1]').addClass('current');
});
describe('when the caption is visible', function() {
beforeEach(function() {
this.player.element.removeClass('closed');
return this.caption.toggle(jQuery.Event('click'));
});
return it('hide the caption', function() {
return expect(this.player.element).toHaveClass('closed');
});
});
return describe('when the caption is hidden', function() {
beforeEach(function() {
this.player.element.addClass('closed');
return this.caption.toggle(jQuery.Event('click'));
});
it('show the caption', function() {
return expect(this.player.element).not.toHaveClass('closed');
});
return it('scroll the caption', function() {
return expect($.fn.scrollTo).toHaveBeenCalled();
});
});
});
});
}).call(this);
(function() {
describe('VideoControl', function() {
beforeEach(function() {
return this.player = jasmine.stubVideoPlayer(this);
});
describe('constructor', function() {
beforeEach(function() {
return this.control = new VideoControl(this.player);
});
it('render the video controls', function() {
return expect($('.video-controls').html()).toContain('<div class="slider"></div>\n<div>\n <ul class="vcr">\n <li><a class="video_control play">Play</a></li>\n <li>\n <div class="vidtime">0:00 / 0:00</div>\n </li>\n </ul>\n <div class="secondary-controls">\n <a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>\n </div>\n</div>');
});
it('bind player events', function() {
expect($(this.player)).toHandleWith('play', this.control.onPlay);
expect($(this.player)).toHandleWith('pause', this.control.onPause);
return expect($(this.player)).toHandleWith('ended', this.control.onPause);
});
return it('bind the playback button', function() {
return expect($('.video_control')).toHandleWith('click', this.control.togglePlayback);
});
});
describe('onPlay', function() {
beforeEach(function() {
this.control = new VideoControl(this.player);
return this.control.onPlay();
});
return it('switch playback button to play state', function() {
expect($('.video_control')).not.toHaveClass('play');
expect($('.video_control')).toHaveClass('pause');
return expect($('.video_control')).toHaveHtml('Pause');
});
});
describe('onPause', function() {
beforeEach(function() {
this.control = new VideoControl(this.player);
return this.control.onPause();
});
return it('switch playback button to pause state', function() {
expect($('.video_control')).not.toHaveClass('pause');
expect($('.video_control')).toHaveClass('play');
return expect($('.video_control')).toHaveHtml('Play');
});
});
return describe('togglePlayback', function() {
beforeEach(function() {
return this.control = new VideoControl(this.player);
});
describe('when the video is playing', function() {
beforeEach(function() {
spyOn(this.player, 'isPlaying').andReturn(true);
spyOnEvent(this.player, 'pause');
return this.control.togglePlayback(jQuery.Event('click'));
});
return it('trigger the pause event', function() {
return expect('pause').toHaveBeenTriggeredOn(this.player);
});
});
return describe('when the video is paused', function() {
beforeEach(function() {
spyOn(this.player, 'isPlaying').andReturn(false);
spyOnEvent(this.player, 'play');
return this.control.togglePlayback(jQuery.Event('click'));
});
return it('trigger the play event', function() {
return expect('play').toHaveBeenTriggeredOn(this.player);
});
});
});
});
}).call(this);
(function() {
describe('VideoPlayer', function() {
beforeEach(function() {
return jasmine.stubVideoPlayer(this);
});
afterEach(function() {
return YT.Player = void 0;
});
describe('constructor', function() {
beforeEach(function() {
spyOn(window, 'VideoControl');
spyOn(YT, 'Player');
$.fn.qtip.andCallFake(function() {
return $(this).data('qtip', true);
});
$('.video').append($('<div class="hide-subtitles" />'));
return this.player = new VideoPlayer(this.video);
});
it('instanticate current time to zero', function() {
return expect(this.player.currentTime).toEqual(0);
});
it('set the element', function() {
return expect(this.player.element).toBe('#video_example');
});
it('create video control', function() {
return expect(window.VideoControl).toHaveBeenCalledWith(this.player);
});
it('create video caption', function() {
return expect(window.VideoCaption).toHaveBeenCalledWith(this.player, 'def456');
});
it('create video speed control', function() {
return expect(window.VideoSpeedControl).toHaveBeenCalledWith(this.player, ['0.75', '1.0']);
});
it('create video progress slider', function() {
return expect(window.VideoProgressSlider).toHaveBeenCalledWith(this.player);
});
it('create Youtube player', function() {
return expect(YT.Player).toHaveBeenCalledWith('example', {
playerVars: {
controls: 0,
wmode: 'transparent',
rel: 0,
showinfo: 0,
enablejsapi: 1
},
videoId: 'def456',
events: {
onReady: this.player.onReady,
onStateChange: this.player.onStateChange
}
});
});
it('bind to seek event', function() {
return expect($(this.player)).toHandleWith('seek', this.player.onSeek);
});
it('bind to updatePlayTime event', function() {
return expect($(this.player)).toHandleWith('updatePlayTime', this.player.onUpdatePlayTime);
});
it('bidn to speedChange event', function() {
return expect($(this.player)).toHandleWith('speedChange', this.player.onSpeedChange);
});
it('bind to play event', function() {
return expect($(this.player)).toHandleWith('play', this.player.onPlay);
});
it('bind to paused event', function() {
return expect($(this.player)).toHandleWith('pause', this.player.onPause);
});
it('bind to ended event', function() {
return expect($(this.player)).toHandleWith('ended', this.player.onPause);
});
it('bind to key press', function() {
return expect($(document)).toHandleWith('keyup', this.player.bindExitFullScreen);
});
it('bind to fullscreen switching button', function() {
return expect($('.add-fullscreen')).toHandleWith('click', this.player.toggleFullScreen);
});
return describe('when not on a touch based device', function() {
return it('add the tooltip to fullscreen and subtitle button', function() {
expect($('.add-fullscreen')).toHaveData('qtip');
return expect($('.hide-subtitles')).toHaveData('qtip');
});
});
});
describe('onReady', function() {
beforeEach(function() {
this.video.embed();
this.player = this.video.player;
spyOnEvent(this.player, 'ready');
spyOnEvent(this.player, 'updatePlayTime');
return this.player.onReady();
});
it('reset the progress to zero', function() {
return expect('updatePlayTime').toHaveBeenTriggeredOn(this.player);
});
it('trigger ready event on the player', function() {
return expect('ready').toHaveBeenTriggeredOn(this.player);
});
describe('when not on a touch based device', function() {
beforeEach(function() {
window.onTouchBasedDevice = function() {
return false;
};
spyOn(this.player, 'play');
return this.player.onReady();
});
return it('autoplay the first video', function() {
return expect(this.player.play).toHaveBeenCalled();
});
});
return describe('when on a touch based device', function() {
beforeEach(function() {
window.onTouchBasedDevice = function() {
return true;
};
spyOn(this.player, 'play');
return this.player.onReady();
});
return it('does not autoplay the first video', function() {
return expect(this.player.play).not.toHaveBeenCalled();
});
});
});
describe('onStateChange', function() {
beforeEach(function() {
return this.player = new VideoPlayer(this.video);
});
describe('when the video is playing', function() {
beforeEach(function() {
spyOnEvent(this.player, 'play');
return this.player.onStateChange({
data: YT.PlayerState.PLAYING
});
});
return it('trigger play event', function() {
return expect('play').toHaveBeenTriggeredOn(this.player);
});
});
describe('when the video is paused', function() {
beforeEach(function() {
spyOnEvent(this.player, 'pause');
return this.player.onStateChange({
data: YT.PlayerState.PAUSED
});
});
return it('trigger pause event', function() {
return expect('pause').toHaveBeenTriggeredOn(this.player);
});
});
return describe('when the video is ended', function() {
beforeEach(function() {
spyOnEvent(this.player, 'ended');
return this.player.onStateChange({
data: YT.PlayerState.ENDED
});
});
return it('trigger ended event', function() {
return expect('ended').toHaveBeenTriggeredOn(this.player);
});
});
});
describe('onPlay', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
this.anotherPlayer = jasmine.createSpyObj('AnotherPlayer', ['pauseVideo']);
window.player = this.anotherPlayer;
spyOn(Logger, 'log');
spyOn(window, 'setInterval').andReturn(100);
this.player.player.getVideoEmbedCode.andReturn('embedCode');
return this.player.onPlay();
});
it('log the play_video event', function() {
return expect(Logger.log).toHaveBeenCalledWith('play_video', {
id: this.player.currentTime,
code: 'embedCode'
});
});
it('pause other video player', function() {
return expect(this.anotherPlayer.pauseVideo).toHaveBeenCalled();
});
it('set current video player as active player', function() {
return expect(window.player).toEqual(this.player.player);
});
return it('set update interval', function() {
expect(window.setInterval).toHaveBeenCalledWith(this.player.update, 200);
return expect(this.player.player.interval).toEqual(100);
});
});
describe('onPause', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
window.player = this.player.player;
spyOn(Logger, 'log');
spyOn(window, 'clearInterval');
this.player.player.interval = 100;
this.player.player.getVideoEmbedCode.andReturn('embedCode');
return this.player.onPause();
});
it('log the pause_video event', function() {
return expect(Logger.log).toHaveBeenCalledWith('pause_video', {
id: this.player.currentTime,
code: 'embedCode'
});
});
it('set current video player as inactive', function() {
return expect(window.player).toBeNull();
});
return it('clear update interval', function() {
expect(window.clearInterval).toHaveBeenCalledWith(100);
return expect(this.player.player.interval).toBeNull();
});
});
describe('onSeek', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
spyOn(window, 'clearInterval');
this.player.player.interval = 100;
return this.player.onSeek({}, 60);
});
it('seek the player', function() {
return expect(this.player.player.seekTo).toHaveBeenCalledWith(60, true);
});
describe('when the player is playing', function() {
beforeEach(function() {
this.player.player.getPlayerState.andReturn(YT.PlayerState.PLAYING);
return this.player.onSeek({}, 60);
});
return it('reset the update interval', function() {
return expect(window.clearInterval).toHaveBeenCalledWith(100);
});
});
return describe('when the player is not playing', function() {
beforeEach(function() {
this.player.player.getPlayerState.andReturn(YT.PlayerState.PAUSED);
spyOnEvent(this.player, 'updatePlayTime');
return this.player.onSeek({}, 60);
});
it('set the current time', function() {
return expect(this.player.currentTime).toEqual(60);
});
return it('trigger updatePlayTime event', function() {
return expect('updatePlayTime').toHaveBeenTriggeredOn(this.player);
});
});
});
describe('onSpeedChange', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
this.player.currentTime = 60;
return spyOn(this.video, 'setSpeed').andCallThrough();
});
describe('always', function() {
beforeEach(function() {
return this.player.onSpeedChange({}, '0.75');
});
it('convert the current time to the new speed', function() {
return expect(this.player.currentTime).toEqual('80.000');
});
return it('set video speed to the new speed', function() {
return expect(this.video.setSpeed).toHaveBeenCalledWith('0.75');
});
});
describe('when the video is playing', function() {
beforeEach(function() {
this.player.player.getPlayerState.andReturn(YT.PlayerState.PLAYING);
spyOnEvent(this.player, 'updatePlayTime');
return this.player.onSpeedChange({}, '0.75');
});
it('load the video', function() {
return expect(this.player.player.loadVideoById).toHaveBeenCalledWith('abc123', '80.000');
});
return it('trigger updatePlayTime event', function() {
return expect('updatePlayTime').toHaveBeenTriggeredOn(this.player);
});
});
return describe('when the video is not playing', function() {
beforeEach(function() {
this.player.player.getPlayerState.andReturn(YT.PlayerState.PAUSED);
spyOnEvent(this.player, 'updatePlayTime');
return this.player.onSpeedChange({}, '0.75');
});
it('cue the video', function() {
return expect(this.player.player.cueVideoById).toHaveBeenCalledWith('abc123', '80.000');
});
return it('trigger updatePlayTime event', function() {
return expect('updatePlayTime').toHaveBeenTriggeredOn(this.player);
});
});
});
describe('update', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
return spyOnEvent(this.player, 'updatePlayTime');
});
describe('when the current time is unavailable from the player', function() {
beforeEach(function() {
this.player.player.getCurrentTime.andReturn(void 0);
return this.player.update();
});
return it('does not trigger updatePlayTime event', function() {
return expect('updatePlayTime').not.toHaveBeenTriggeredOn(this.player);
});
});
return describe('when the current time is available from the player', function() {
beforeEach(function() {
this.player.player.getCurrentTime.andReturn(60);
return this.player.update();
});
return it('trigger updatePlayTime event', function() {
return expect('updatePlayTime').toHaveBeenTriggeredOn(this.player);
});
});
});
describe('onUpdatePlaytime', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
spyOn(this.video, 'getDuration').andReturn(1800);
return this.player.onUpdatePlayTime({}, 60);
});
return it('update the video playback time', function() {
return expect($('.vidtime')).toHaveHtml('1:00 / 30:00');
});
});
describe('toggleFullScreen', function() {
beforeEach(function() {
return this.player = new VideoPlayer(this.video);
});
describe('when the video player is not full screen', function() {
beforeEach(function() {
this.player.element.removeClass('fullscreen');
spyOnEvent(this.player, 'resize');
return this.player.toggleFullScreen(jQuery.Event("click"));
});
it('replace the full screen button tooltip', function() {
return expect($('.add-fullscreen')).toHaveAttr('title', 'Exit fill browser');
});
it('add a new exit from fullscreen button', function() {
return expect(this.player.element).toContain('a.exit');
});
it('add the fullscreen class', function() {
return expect(this.player.element).toHaveClass('fullscreen');
});
return it('trigger resize event', function() {
return expect('resize').toHaveBeenTriggeredOn(this.player);
});
});
return describe('when the video player already full screen', function() {
beforeEach(function() {
this.player.element.addClass('fullscreen');
spyOnEvent(this.player, 'resize');
return this.player.toggleFullScreen(jQuery.Event("click"));
});
it('replace the full screen button tooltip', function() {
return expect($('.add-fullscreen')).toHaveAttr('title', 'Fill browser');
});
it('remove exit full screen button', function() {
return expect(this.player.element).not.toContain('a.exit');
});
it('remove the fullscreen class', function() {
return expect(this.player.element).not.toHaveClass('fullscreen');
});
return it('trigger resize event', function() {
return expect('resize').toHaveBeenTriggeredOn(this.player);
});
});
});
describe('play', function() {
beforeEach(function() {
return this.player = new VideoPlayer(this.video);
});
describe('when the player is not ready', function() {
beforeEach(function() {
this.player.player.playVideo = void 0;
return this.player.play();
});
return it('does nothing', function() {
return expect(this.player.player.playVideo).toBeUndefined();
});
});
return describe('when the player is ready', function() {
beforeEach(function() {
this.player.player.playVideo.andReturn(true);
return this.player.play();
});
return it('delegate to the Youtube player', function() {
return expect(this.player.player.playVideo).toHaveBeenCalled();
});
});
});
describe('isPlaying', function() {
beforeEach(function() {
return this.player = new VideoPlayer(this.video);
});
describe('when the video is playing', function() {
beforeEach(function() {
return this.player.player.getPlayerState.andReturn(YT.PlayerState.PLAYING);
});
return it('return true', function() {
return expect(this.player.isPlaying()).toBeTruthy();
});
});
return describe('when the video is not playing', function() {
beforeEach(function() {
return this.player.player.getPlayerState.andReturn(YT.PlayerState.PAUSED);
});
return it('return false', function() {
return expect(this.player.isPlaying()).toBeFalsy();
});
});
});
describe('pause', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
return this.player.pause();
});
return it('delegate to the Youtube player', function() {
return expect(this.player.player.pauseVideo).toHaveBeenCalled();
});
});
describe('duration', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
spyOn(this.video, 'getDuration');
return this.player.duration();
});
return it('delegate to the video', function() {
return expect(this.video.getDuration).toHaveBeenCalled();
});
});
return describe('currentSpeed', function() {
beforeEach(function() {
this.player = new VideoPlayer(this.video);
return this.video.speed = '3.0';
});
return it('delegate to the video', function() {
return expect(this.player.currentSpeed()).toEqual('3.0');
});
});
});
}).call(this);
(function() {
describe('VideoProgressSlider', function() {
beforeEach(function() {
return this.player = jasmine.stubVideoPlayer(this);
});
describe('constructor', function() {
beforeEach(function() {
spyOn($.fn, 'slider').andCallThrough();
return this.slider = new VideoProgressSlider(this.player);
});
it('build the slider', function() {
expect(this.slider.slider).toBe('.slider');
return expect($.fn.slider).toHaveBeenCalledWith({
range: 'min',
change: this.slider.onChange,
slide: this.slider.onSlide,
stop: this.slider.onStop
});
});
it('build the seek handle', function() {
expect(this.slider.handle).toBe('.ui-slider-handle');
return expect($.fn.qtip).toHaveBeenCalledWith({
content: "0:00",
position: {
my: 'bottom center',
at: 'top center',
container: this.slider.handle
},
hide: {
delay: 700
},
style: {
classes: 'ui-tooltip-slider',
widget: true
}
});
});
return it('bind player events', function() {
return expect($(this.player)).toHandleWith('updatePlayTime', this.slider.onUpdatePlayTime);
});
});
describe('onReady', function() {
beforeEach(function() {
spyOn(this.player, 'duration').andReturn(120);
this.slider = new VideoProgressSlider(this.player);
return this.slider.onReady();
});
return it('set the max value to the length of video', function() {
return expect(this.slider.slider.slider('option', 'max')).toEqual(120);
});
});
describe('onUpdatePlayTime', function() {
beforeEach(function() {
this.slider = new VideoProgressSlider(this.player);
spyOn(this.player, 'duration').andReturn(120);
return spyOn($.fn, 'slider').andCallThrough();
});
describe('when frozen', function() {
beforeEach(function() {
this.slider.frozen = true;
return this.slider.onUpdatePlayTime({}, 20);
});
return it('does not update the slider', function() {
return expect($.fn.slider).not.toHaveBeenCalled();
});
});
return describe('when not frozen', function() {
beforeEach(function() {
this.slider.frozen = false;
return this.slider.onUpdatePlayTime({}, 20);
});
it('update the max value of the slider', function() {
return expect($.fn.slider).toHaveBeenCalledWith('option', 'max', 120);
});
return it('update current value of the slider', function() {
return expect($.fn.slider).toHaveBeenCalledWith('value', 20);
});
});
});
describe('onSlide', function() {
beforeEach(function() {
var _this = this;
this.slider = new VideoProgressSlider(this.player);
this.time = null;
$(this.player).bind('seek', function(event, time) {
return _this.time = time;
});
spyOnEvent(this.player, 'seek');
return this.slider.onSlide({}, {
value: 20
});
});
it('freeze the slider', function() {
return expect(this.slider.frozen).toBeTruthy();
});
it('update the tooltip', function() {
return expect($.fn.qtip).toHaveBeenCalled();
});
return it('trigger seek event', function() {
expect('seek').toHaveBeenTriggeredOn(this.player);
return expect(this.time).toEqual(20);
});
});
describe('onChange', function() {
beforeEach(function() {
this.slider = new VideoProgressSlider(this.player);
return this.slider.onChange({}, {
value: 20
});
});
return it('update the tooltip', function() {
return expect($.fn.qtip).toHaveBeenCalled();
});
});
describe('onStop', function() {
beforeEach(function() {
var _this = this;
this.slider = new VideoProgressSlider(this.player);
this.time = null;
$(this.player).bind('seek', function(event, time) {
return _this.time = time;
});
spyOnEvent(this.player, 'seek');
spyOn(window, 'setTimeout');
return this.slider.onStop({}, {
value: 20
});
});
it('freeze the slider', function() {
return expect(this.slider.frozen).toBeTruthy();
});
it('trigger seek event', function() {
expect('seek').toHaveBeenTriggeredOn(this.player);
return expect(this.time).toEqual(20);
});
return it('set timeout to unfreeze the slider', function() {
expect(window.setTimeout).toHaveBeenCalledWith(jasmine.any(Function), 200);
window.setTimeout.mostRecentCall.args[0]();
return expect(this.slider.frozen).toBeFalsy();
});
});
return describe('updateTooltip', function() {
beforeEach(function() {
this.slider = new VideoProgressSlider(this.player);
return this.slider.updateTooltip(90);
});
return it('set the tooltip value', function() {
return expect($.fn.qtip).toHaveBeenCalledWith('option', 'content.text', '1:30');
});
});
});
}).call(this);
(function() {
describe('VideoSpeedControl', function() {
beforeEach(function() {
this.player = jasmine.stubVideoPlayer(this);
return $('.speeds').remove();
});
afterEach(function() {});
describe('constructor', function() {
describe('always', function() {
beforeEach(function() {
return this.speedControl = new VideoSpeedControl(this.player, this.video.speeds);
});
it('add the video speed control to player', function() {
return expect($('.secondary-controls').html()).toContain('<div class="speeds">\n <a href="#">\n <h3>Speed</h3>\n <p class="active">1.0x</p>\n </a>\n <ol class="video_speeds"><li data-speed="1.0" class="active"><a href="#">1.0x</a></li><li data-speed="0.75"><a href="#">0.75x</a></li></ol>\n</div>');
});
it('bind to player speedChange event', function() {
return expect($(this.player)).toHandleWith('speedChange', this.speedControl.onSpeedChange);
});
return it('bind to change video speed link', function() {
return expect($('.video_speeds a')).toHandleWith('click', this.speedControl.changeVideoSpeed);
});
});
describe('when running on touch based device', function() {
beforeEach(function() {
spyOn(window, 'onTouchBasedDevice').andReturn(true);
$('.speeds').removeClass('open');
return this.speedControl = new VideoSpeedControl(this.player, this.video.speeds);
});
return it('open the speed toggle on click', function() {
$('.speeds').click();
expect($('.speeds')).toHaveClass('open');
$('.speeds').click();
return expect($('.speeds')).not.toHaveClass('open');
});
});
return describe('when running on non-touch based device', function() {
beforeEach(function() {
spyOn(window, 'onTouchBasedDevice').andReturn(false);
$('.speeds').removeClass('open');
return this.speedControl = new VideoSpeedControl(this.player, this.video.speeds);
});
it('open the speed toggle on hover', function() {
$('.speeds').mouseover();
expect($('.speeds')).toHaveClass('open');
$('.speeds').mouseout();
return expect($('.speeds')).not.toHaveClass('open');
});
it('close the speed toggle on mouse out', function() {
$('.speeds').mouseover().mouseout();
return expect($('.speeds')).not.toHaveClass('open');
});
return it('close the speed toggle on click', function() {
$('.speeds').mouseover().click();
return expect($('.speeds')).not.toHaveClass('open');
});
});
});
describe('changeVideoSpeed', function() {
beforeEach(function() {
this.speedControl = new VideoSpeedControl(this.player, this.video.speeds);
return this.video.setSpeed('1.0');
});
describe('when new speed is the same', function() {
beforeEach(function() {
spyOnEvent(this.player, 'speedChange');
return $('li[data-speed="1.0"] a').click();
});
return it('does not trigger speedChange event', function() {
return expect('speedChange').not.toHaveBeenTriggeredOn(this.player);
});
});
return describe('when new speed is not the same', function() {
beforeEach(function() {
var _this = this;
this.newSpeed = null;
$(this.player).bind('speedChange', function(event, newSpeed) {
return _this.newSpeed = newSpeed;
});
spyOnEvent(this.player, 'speedChange');
return $('li[data-speed="0.75"] a').click();
});
return it('trigger player speedChange event', function() {
expect('speedChange').toHaveBeenTriggeredOn(this.player);
return expect(this.newSpeed).toEqual(0.75);
});
});
});
return describe('onSpeedChange', function() {
beforeEach(function() {
this.speedControl = new VideoSpeedControl(this.player, this.video.speeds);
$('li[data-speed="1.0"] a').addClass('active');
return this.speedControl.setSpeed('0.75');
});
return it('set the new speed as active', function() {
expect($('.video_speeds li[data-speed="1.0"]')).not.toHaveClass('active');
expect($('.video_speeds li[data-speed="0.75"]')).toHaveClass('active');
return expect($('.speeds p.active')).toHaveHtml('0.75x');
});
});
});
}).call(this);
(function() {
describe('Video', function() {
beforeEach(function() {
loadFixtures('video.html');
return jasmine.stubRequests();
});
afterEach(function() {
window.player = void 0;
return window.onYouTubePlayerAPIReady = void 0;
});
describe('constructor', function() {
beforeEach(function() {
$.cookie.andReturn('0.75');
return window.player = 100;
});
describe('by default', function() {
beforeEach(function() {
return this.video = new Video('example', '.75:abc123,1.0:def456');
});
it('reset the current video player', function() {
return expect(window.player).toBeNull();
});
it('set the elements', function() {
return expect(this.video.element).toBe('#video_example');
});
it('parse the videos', function() {
return expect(this.video.videos).toEqual({
'0.75': 'abc123',
'1.0': 'def456'
});
});
it('fetch the video metadata', function() {
return expect(this.video.metadata).toEqual({
abc123: {
id: 'abc123',
duration: 100
},
def456: {
id: 'def456',
duration: 200
}
});
});
it('parse available video speeds', function() {
return expect(this.video.speeds).toEqual(['0.75', '1.0']);
});
it('set current video speed via cookie', function() {
return expect(this.video.speed).toEqual('0.75');
});
return it('store a reference for this video player in the element', function() {
return expect($('.video').data('video')).toEqual(this.video);
});
});
describe('when the Youtube API is already available', function() {
beforeEach(function() {
this.originalYT = window.YT;
window.YT = {
Player: true
};
this.stubVideoPlayer = jasmine.createSpy('VideoPlayer');
spyOn(window, 'VideoPlayer').andReturn(this.stubVideoPlayer);
return this.video = new Video('example', '.75:abc123,1.0:def456');
});
afterEach(function() {
return window.YT = this.originalYT;
});
return it('create the Video Player', function() {
expect(window.VideoPlayer).toHaveBeenCalledWith(this.video);
return expect(this.video.player).toEqual(this.stubVideoPlayer);
});
});
describe('when the Youtube API is not ready', function() {
beforeEach(function() {
return this.video = new Video('example', '.75:abc123,1.0:def456');
});
return it('set the callback on the window object', function() {
return expect(window.onYouTubePlayerAPIReady).toEqual(jasmine.any(Function));
});
});
return describe('when the Youtube API becoming ready', function() {
beforeEach(function() {
this.stubVideoPlayer = jasmine.createSpy('VideoPlayer');
spyOn(window, 'VideoPlayer').andReturn(this.stubVideoPlayer);
this.video = new Video('example', '.75:abc123,1.0:def456');
return window.onYouTubePlayerAPIReady();
});
return it('create the Video Player for all video elements', function() {
expect(window.VideoPlayer).toHaveBeenCalledWith(this.video);
return expect(this.video.player).toEqual(this.stubVideoPlayer);
});
});
});
describe('youtubeId', function() {
beforeEach(function() {
$.cookie.andReturn('1.0');
return this.video = new Video('example', '.75:abc123,1.0:def456');
});
describe('with speed', function() {
return it('return the video id for given speed', function() {
expect(this.video.youtubeId('0.75')).toEqual('abc123');
return expect(this.video.youtubeId('1.0')).toEqual('def456');
});
});
return describe('without speed', function() {
return it('return the video id for current speed', function() {
return expect(this.video.youtubeId()).toEqual('def456');
});
});
});
describe('setSpeed', function() {
beforeEach(function() {
return this.video = new Video('example', '.75:abc123,1.0:def456');
});
describe('when new speed is available', function() {
beforeEach(function() {
return this.video.setSpeed('0.75');
});
it('set new speed', function() {
return expect(this.video.speed).toEqual('0.75');
});
return it('save setting for new speed', function() {
return expect($.cookie).toHaveBeenCalledWith('video_speed', '0.75', {
expires: 3650,
path: '/'
});
});
});
return describe('when new speed is not available', function() {
beforeEach(function() {
return this.video.setSpeed('1.75');
});
return it('set speed to 1.0x', function() {
return expect(this.video.speed).toEqual('1.0');
});
});
});
return describe('getDuration', function() {
beforeEach(function() {
return this.video = new Video('example', '.75:abc123,1.0:def456');
});
return it('return duration for current video', function() {
return expect(this.video.getDuration()).toEqual(200);
});
});
});
}).call(this);
(function() {
describe('Navigation', function() {
beforeEach(function() {
loadFixtures('accordion.html');
return this.navigation = new Navigation;
});
describe('constructor', function() {
describe('when the #accordion exists', function() {
describe('when there is an active section', function() {
beforeEach(function() {
spyOn($.fn, 'accordion');
$('#accordion').append('<ul><li></li></ul><ul><li class="active"></li></ul>');
return new Navigation;
});
return it('activate the accordion with correct active section', function() {
return expect($('#accordion').accordion).toHaveBeenCalledWith({
active: 1,
header: 'h3',
autoHeight: false
});
});
});
describe('when there is no active section', function() {
beforeEach(function() {
spyOn($.fn, 'accordion');
$('#accordion').append('<ul><li></li></ul><ul><li></li></ul>');
return new Navigation;
});
return it('activate the accordian with section 1 as active', function() {
return expect($('#accordion').accordion).toHaveBeenCalledWith({
active: 1,
header: 'h3',
autoHeight: false
});
});
});
it('binds the accordionchange event', function() {
Navigation.bind();
return expect($('#accordion')).toHandleWith('accordionchange', this.navigation.log);
});
return it('bind the navigation toggle', function() {
Navigation.bind();
return expect($('#open_close_accordion a')).toHandleWith('click', this.navigation.toggle);
});
});
return describe('when the #accordion does not exists', function() {
beforeEach(function() {
return $('#accordion').remove();
});
return it('does not activate the accordion', function() {
spyOn($.fn, 'accordion');
Navigation.bind();
return expect($('#accordion').accordion).wasNotCalled();
});
});
});
describe('toggle', function() {
return it('toggle closed class on the wrapper', function() {
$('.course-wrapper').removeClass('closed');
this.navigation.toggle();
expect($('.course-wrapper')).toHaveClass('closed');
this.navigation.toggle();
return expect($('.course-wrapper')).not.toHaveClass('closed');
});
});
return describe('log', function() {
beforeEach(function() {
window.log_event = function() {};
return spyOn(window, 'log_event');
});
return it('submit event log', function() {
this.navigation.log({}, {
newHeader: {
text: function() {
return "new";
}
},
oldHeader: {
text: function() {
return "old";
}
}
});
return expect(window.log_event).toHaveBeenCalledWith('accordion', {
newheader: 'new',
oldheader: 'old'
});
});
});
});
}).call(this);
(function() {
describe('Time', function() {
describe('format', function() {
describe('with duration more than or equal to 1 hour', function() {
return it('return a correct time format', function() {
expect(Time.format(3600)).toEqual('1:00:00');
return expect(Time.format(7272)).toEqual('2:01:12');
});
});
return describe('with duration less than 1 hour', function() {
return it('return a correct time format', function() {
expect(Time.format(1)).toEqual('0:01');
expect(Time.format(61)).toEqual('1:01');
return expect(Time.format(3599)).toEqual('59:59');
});
});
});
return describe('convert', function() {
return it('return a correct time based on speed modifier', function() {
expect(Time.convert(0, 1, 1.5)).toEqual('0.000');
expect(Time.convert(100, 1, 1.5)).toEqual('66.667');
return expect(Time.convert(100, 1.5, 1)).toEqual('150.000');
});
});
});
}).call(this);
...@@ -16,15 +16,12 @@ ...@@ -16,15 +16,12 @@
<script src="{{ url }}"></script> <script src="{{ url }}"></script>
{% endfor %} {% endfor %}
{% load compressed %}
{# static files #} {# static files #}
{% for url in suite.static_files %} {% compressed_js 'application' %}
<script src="{{ STATIC_URL }}{{ url }}"></script>
{% endfor %}
{# spec files #} {# spec files #}
{% for file in files %} {% compressed_js 'spec' %}
<script src="{% url jasmine_test file %}"></script>
{% endfor %}
</head> </head>
<body> <body>
......
...@@ -117,10 +117,6 @@ ...@@ -117,10 +117,6 @@
<script type="text/javascript" src="${static.url('js/schematic.js')}"></script> <script type="text/javascript" src="${static.url('js/schematic.js')}"></script>
<script type="text/javascript" src="${static.url('js/cktsim.js')}"></script> <script type="text/javascript" src="${static.url('js/cktsim.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery.scrollTo-1.4.2-min.js')}"></script> <script type="text/javascript" src="${static.url('js/jquery.scrollTo-1.4.2-min.js')}"></script>
<script type="text/javascript">
document.write('\x3Cscript type="text/javascript" src="' +
document.location.protocol + '//www.youtube.com/player_api">\x3C/script>');
</script>
<%block name="js_extra"/> <%block name="js_extra"/>
</body> </body>
</html> </html>
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