diff --git a/static/coffee/files.json b/static/coffee/files.json index 67bf671f6a..1e5e010d73 100644 --- a/static/coffee/files.json +++ b/static/coffee/files.json @@ -3,7 +3,7 @@ "/static/js/jquery-1.6.2.min.js", "/static/js/jquery-ui-1.8.16.custom.min.js", "/static/js/jquery.leanModal.js", - "/static/js/jquery.cookie.js" + "/static/js/flot/jquery.flot.js" ], "static_files": [ "js/application.js" diff --git a/static/coffee/spec/calculator_spec.coffee b/static/coffee/spec/calculator_spec.coffee index a9ef69ed26..58d7c70790 100644 --- a/static/coffee/spec/calculator_spec.coffee +++ b/static/coffee/spec/calculator_spec.coffee @@ -24,6 +24,7 @@ describe 'Calculator', -> expect($('form#calculator')).toHandleWith 'submit', @calculator.calculate it 'prevent default behavior on form submit', -> + jasmine.stubRequests() $('form#calculator').submit (e) -> expect(e.isDefaultPrevented()).toBeTruthy() e.preventDefault() @@ -55,7 +56,7 @@ describe 'Calculator', -> describe 'calculate', -> beforeEach -> $('#calculator_input').val '1+2' - spyOn($, 'getJSON').andCallFake (url, data, callback) -> + spyOn($, 'getWithPrefix').andCallFake (url, data, callback) -> callback({ result: 3 }) @calculator.calculate() diff --git a/static/coffee/spec/calculator_spec.js b/static/coffee/spec/calculator_spec.js index 66033964de..4bc54700a5 100644 --- a/static/coffee/spec/calculator_spec.js +++ b/static/coffee/spec/calculator_spec.js @@ -26,6 +26,7 @@ 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(); @@ -58,7 +59,7 @@ return describe('calculate', function() { beforeEach(function() { $('#calculator_input').val('1+2'); - spyOn($, 'getJSON').andCallFake(function(url, data, callback) { + spyOn($, 'getWithPrefix').andCallFake(function(url, data, callback) { return callback({ result: 3 }); diff --git a/static/coffee/spec/courseware_spec.coffee b/static/coffee/spec/courseware_spec.coffee index 91b9187668..9d938c14e1 100644 --- a/static/coffee/spec/courseware_spec.coffee +++ b/static/coffee/spec/courseware_spec.coffee @@ -35,16 +35,28 @@ describe 'Courseware', -> describe 'render', -> beforeEach -> + jasmine.stubRequests() @courseware = new Courseware + spyOn(window, 'Histogram') + spyOn(window, 'Problem') + spyOn(window, 'Video') setFixtures """
+
+
+
""" - - it 'detect the video element and convert them', -> - spyOn(window, 'Video') @courseware.render() + + it 'detect the video elements and convert them', -> expect(window.Video).toHaveBeenCalledWith('1', '1.0:abc1234') expect(window.Video).toHaveBeenCalledWith('2', '1.0:def5678') + + it 'detect the problem element and convert it', -> + expect(window.Problem).toHaveBeenCalledWith('3', '/example/url/') + + it 'detect the histrogram element and convert it', -> + expect(window.Histogram).toHaveBeenCalledWith('3', [[0, 1]]) diff --git a/static/coffee/spec/courseware_spec.js b/static/coffee/spec/courseware_spec.js index adb04adc49..757943118c 100644 --- a/static/coffee/spec/courseware_spec.js +++ b/static/coffee/spec/courseware_spec.js @@ -35,15 +35,24 @@ }); return describe('render', function() { beforeEach(function() { + jasmine.stubRequests(); this.courseware = new Courseware; - return setFixtures("
\n
\n
\n
"); - }); - return it('detect the video element and convert them', function() { + spyOn(window, 'Histogram'); + spyOn(window, 'Problem'); spyOn(window, 'Video'); - this.courseware.render(); + setFixtures("
\n
\n
\n
\n
\n
\n
"); + 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]]); + }); }); }); diff --git a/static/coffee/spec/feedback_form_spec.coffee b/static/coffee/spec/feedback_form_spec.coffee index 64fa5cba24..ce4195faab 100644 --- a/static/coffee/spec/feedback_form_spec.coffee +++ b/static/coffee/spec/feedback_form_spec.coffee @@ -5,7 +5,7 @@ describe 'FeedbackForm', -> describe 'constructor', -> beforeEach -> new FeedbackForm - spyOn($, 'post').andCallFake (url, data, callback, format) -> + spyOn($, 'postWithPrefix').andCallFake (url, data, callback, format) -> callback() it 'binds to the #feedback_button', -> diff --git a/static/coffee/spec/feedback_form_spec.js b/static/coffee/spec/feedback_form_spec.js index 4a02b4d541..eb5546baa1 100644 --- a/static/coffee/spec/feedback_form_spec.js +++ b/static/coffee/spec/feedback_form_spec.js @@ -7,7 +7,7 @@ return describe('constructor', function() { beforeEach(function() { new FeedbackForm; - return spyOn($, 'post').andCallFake(function(url, data, callback, format) { + return spyOn($, 'postWithPrefix').andCallFake(function(url, data, callback, format) { return callback(); }); }); diff --git a/static/coffee/spec/helper.coffee b/static/coffee/spec/helper.coffee index 1f27e257c2..c81cb83405 100644 --- a/static/coffee/spec/helper.coffee +++ b/static/coffee/spec/helper.coffee @@ -1 +1,76 @@ 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 = -> + spyOn($, 'ajax').andCallFake (settings) -> + if match = settings.url.match /youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/ + settings.success data: jasmine.stubbedMetadata[match[1]] + else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/ + 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)$/) + # do nothing + else + throw "External request attempted for #{settings.url}, which is not defined." + +jasmine.stubYoutubePlayer = -> + YT.Player = -> jasmine.createSpyObj 'YT.Player', ['cueVideoById', 'getVideoEmbedCode', + 'getCurrentTime', 'getPlayerState', 'loadVideoById', 'playVideo', 'pauseVideo', 'seekTo'] + +jasmine.stubVideoPlayer = (context, enableParts) -> + enableParts = [enableParts] unless $.isArray(enableParts) + + suite = context.suite + currentPartName = suite.description while suite = suite.parentSuite + enableParts.push currentPartName + + for part in ['VideoCaption', 'VideoSpeedControl', 'VideoProgressSlider'] + unless $.inArray(part, enableParts) >= 0 + spyOn window, part + + loadFixtures 'video.html' + jasmine.stubRequests() + YT.Player = undefined + context.video = new Video 'example', '.75:abc123,1.0:def456' + jasmine.stubYoutubePlayer() + return new VideoPlayer context.video + +spyOn(window, 'onunload') + +# Stub Youtube API +window.YT = + PlayerState: + UNSTARTED: -1 + ENDED: 0 + PLAYING: 1 + PAUSED: 2 + BUFFERING: 3 + CUED: 5 + +# Stub jQuery.cookie +$.cookie = jasmine.createSpy('jQuery.cookie').andReturn '1.0' + +# Stub jQuery.qtip +$.fn.qtip = jasmine.createSpy 'jQuery.qtip' + +# Stub jQuery.scrollTo +$.fn.scrollTo = jasmine.createSpy 'jQuery.scrollTo' diff --git a/static/coffee/spec/helper.js b/static/coffee/spec/helper.js index 3add5f2bf8..0abaa18090 100644 --- a/static/coffee/spec/helper.js +++ b/static/coffee/spec/helper.js @@ -2,4 +2,90 @@ 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); diff --git a/static/coffee/src/courseware.coffee b/static/coffee/src/courseware.coffee index 697aff8af4..e110dfe0ac 100644 --- a/static/coffee/src/courseware.coffee +++ b/static/coffee/src/courseware.coffee @@ -1,4 +1,6 @@ class @Courseware + @prefix: '' + constructor: -> Courseware.prefix = $("meta[name='path_prefix']").attr('content') new Navigation @@ -25,4 +27,3 @@ class @Courseware $('.course-content .histogram').each -> id = $(this).attr('id').replace(/histogram_/, '') new Histogram id, $(this).data('histogram') - diff --git a/templates/coffee/fixtures/items.json b/templates/coffee/fixtures/items.json new file mode 100644 index 0000000000..df37531f3f --- /dev/null +++ b/templates/coffee/fixtures/items.json @@ -0,0 +1,15 @@ +[ + { + "content": "\"Video 1\"", + "type": "video", + "title": "Video 1" + }, { + "content": "\"Video 2\"", + "type": "video", + "title": "Video 2" + }, { + "content": "\"Sample Problem\"", + "type": "problem", + "title": "Sample Problem" + } +] diff --git a/templates/coffee/fixtures/problem.html b/templates/coffee/fixtures/problem.html new file mode 100644 index 0000000000..f77ece7845 --- /dev/null +++ b/templates/coffee/fixtures/problem.html @@ -0,0 +1 @@ +
diff --git a/templates/coffee/fixtures/problem_content.html b/templates/coffee/fixtures/problem_content.html new file mode 100644 index 0000000000..d2e89fed2b --- /dev/null +++ b/templates/coffee/fixtures/problem_content.html @@ -0,0 +1,16 @@ +

Problem Header

+ +
+

Problem Content

+ +
+ + + + + + + Explanation +
+
+
diff --git a/templates/coffee/fixtures/sequence.html b/templates/coffee/fixtures/sequence.html new file mode 100644 index 0000000000..53e9531dd2 --- /dev/null +++ b/templates/coffee/fixtures/sequence.html @@ -0,0 +1,20 @@ +
+ + +
+ + +
diff --git a/templates/coffee/fixtures/tab.html b/templates/coffee/fixtures/tab.html new file mode 100644 index 0000000000..7d28fa2ad7 --- /dev/null +++ b/templates/coffee/fixtures/tab.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/templates/coffee/fixtures/video.html b/templates/coffee/fixtures/video.html new file mode 100644 index 0000000000..15404a89d1 --- /dev/null +++ b/templates/coffee/fixtures/video.html @@ -0,0 +1,12 @@ +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/coffee/spec/histogram_spec.coffee b/templates/coffee/spec/histogram_spec.coffee new file mode 100644 index 0000000000..4fd7ef98c3 --- /dev/null +++ b/templates/coffee/spec/histogram_spec.coffee @@ -0,0 +1,46 @@ +describe 'Histogram', -> + beforeEach -> + spyOn $, 'plot' + + describe 'constructor', -> + it 'instantiate the data arrays', -> + histogram = new Histogram 1, [] + expect(histogram.xTicks).toEqual [] + expect(histogram.yTicks).toEqual [] + expect(histogram.data).toEqual [] + + describe 'calculate', -> + beforeEach -> + @histogram = new Histogram(1, [[1, 1], [2, 2], [3, 3]]) + + it 'store the correct value for data', -> + expect(@histogram.data).toEqual [[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]] + + it 'store the correct value for x ticks', -> + expect(@histogram.xTicks).toEqual [[1, '1'], [2, '2'], [3, '3']] + + it 'store the correct value for y ticks', -> + expect(@histogram.yTicks).toEqual + + describe 'render', -> + it 'call flot with correct option', -> + new Histogram(1, [[1, 1], [2, 2], [3, 3]]) + 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 diff --git a/templates/coffee/spec/histogram_spec.js b/templates/coffee/spec/histogram_spec.js new file mode 100644 index 0000000000..edfeec15d5 --- /dev/null +++ b/templates/coffee/spec/histogram_spec.js @@ -0,0 +1,62 @@ +(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); diff --git a/templates/coffee/spec/logger_spec.coffee b/templates/coffee/spec/logger_spec.coffee new file mode 100644 index 0000000000..bfad742de3 --- /dev/null +++ b/templates/coffee/spec/logger_spec.coffee @@ -0,0 +1,35 @@ +describe 'Logger', -> + it 'expose window.log_event', -> + jasmine.stubRequests() + expect(window.log_event).toBe Logger.log + + describe 'log', -> + it 'send a request to log event', -> + spyOn $, 'getWithPrefix' + Logger.log 'example', 'data' + expect($.getWithPrefix).toHaveBeenCalledWith '/event', + event_type: 'example' + event: '"data"' + page: window.location.href + + describe 'bind', -> + beforeEach -> + Logger.bind() + Courseware.prefix = '/6002x' + + afterEach -> + window.onunload = null + + it 'bind the onunload event', -> + expect(window.onunload).toEqual jasmine.any(Function) + + it 'send a request to log event', -> + spyOn($, 'ajax') + $(window).trigger('onunload') + expect($.ajax).toHaveBeenCalledWith + url: "#{Courseware.prefix}/event", + data: + event_type: 'page_close' + event: '' + page: window.location.href + async: false diff --git a/templates/coffee/spec/logger_spec.js b/templates/coffee/spec/logger_spec.js new file mode 100644 index 0000000000..86b184a873 --- /dev/null +++ b/templates/coffee/spec/logger_spec.js @@ -0,0 +1,46 @@ +(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); diff --git a/templates/coffee/spec/modules/problem_spec.coffee b/templates/coffee/spec/modules/problem_spec.coffee new file mode 100644 index 0000000000..6bca63cfe1 --- /dev/null +++ b/templates/coffee/spec/modules/problem_spec.coffee @@ -0,0 +1,250 @@ +describe 'Problem', -> + beforeEach -> + # Stub MathJax + window.MathJax = { Hub: { Queue: -> } } + window.update_schematics = -> + + loadFixtures 'problem.html' + spyOn Logger, 'log' + spyOn($.fn, 'load').andCallFake (url, callback) -> + $(@).html readFixtures('problem_content.html') + callback() + + describe 'constructor', -> + beforeEach -> + @problem = new Problem 1, '/problem/url/' + + it 'set the element', -> + expect(@problem.element).toBe '#problem_1' + + it 'set the content url', -> + expect(@problem.content_url).toEqual '/problem/url/problem_get?id=1' + + it 'render the content', -> + expect($.fn.load).toHaveBeenCalledWith @problem.content_url, @problem.bind + + describe 'bind', -> + beforeEach -> + spyOn MathJax.Hub, 'Queue' + spyOn window, 'update_schematics' + @problem = new Problem 1, '/problem/url/' + + it 'set mathjax typeset', -> + expect(MathJax.Hub.Queue).toHaveBeenCalled() + + it 'update schematics', -> + expect(window.update_schematics).toHaveBeenCalled() + + it 'bind answer refresh on button click', -> + expect($('section.action input:button')).toHandleWith 'click', @problem.refreshAnswers + + it 'bind the check button', -> + expect($('section.action input.check')).toHandleWith 'click', @problem.check + + it 'bind the reset button', -> + expect($('section.action input.reset')).toHandleWith 'click', @problem.reset + + it 'bind the show button', -> + expect($('section.action input.show')).toHandleWith 'click', @problem.show + + it 'bind the save button', -> + expect($('section.action input.save')).toHandleWith 'click', @problem.save + + describe 'render', -> + beforeEach -> + @problem = new Problem 1, '/problem/url/' + @bind = @problem.bind + spyOn @problem, 'bind' + + describe 'with content given', -> + beforeEach -> + @problem.render 'Hello World' + + it 'render the content', -> + expect(@problem.element.html()).toEqual 'Hello World' + + it 're-bind the content', -> + expect(@problem.bind).toHaveBeenCalled() + + describe 'with no content given', -> + it 'load the content via ajax', -> + expect($.fn.load).toHaveBeenCalledWith @problem.content_url, @bind + + describe 'check', -> + beforeEach -> + jasmine.stubRequests() + @problem = new Problem 1, '/problem/url/' + @problem.answers = 'foo=1&bar=2' + + it 'log the problem_check event', -> + @problem.check() + expect(Logger.log).toHaveBeenCalledWith 'problem_check', 'foo=1&bar=2' + + it 'submit the answer for check', -> + spyOn $, 'postWithPrefix' + @problem.check() + expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_check', 'foo=1&bar=2', jasmine.any(Function) + + describe 'when the response is correct', -> + it 'call render with returned content', -> + spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'correct', contents: 'Correct!') + @problem.check() + expect(@problem.element.html()).toEqual 'Correct!' + + describe 'when the response is incorrect', -> + it 'call render with returned content', -> + spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'incorrect', contents: 'Correct!') + @problem.check() + expect(@problem.element.html()).toEqual 'Correct!' + + describe 'when the response is undetermined', -> + it 'alert the response', -> + spyOn window, 'alert' + spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'Number Only!') + @problem.check() + expect(window.alert).toHaveBeenCalledWith 'Number Only!' + + describe 'reset', -> + beforeEach -> + jasmine.stubRequests() + @problem = new Problem 1, '/problem/url/' + + it 'log the problem_reset event', -> + @problem.answers = 'foo=1&bar=2' + @problem.reset() + expect(Logger.log).toHaveBeenCalledWith 'problem_reset', 'foo=1&bar=2' + + it 'POST to the problem reset page', -> + spyOn $, 'postWithPrefix' + @problem.reset() + expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_reset', { id: 1 }, jasmine.any(Function) + + it 'render the returned content', -> + spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback("Reset!") + @problem.reset() + expect(@problem.element.html()).toEqual 'Reset!' + + describe 'show', -> + beforeEach -> + jasmine.stubRequests() + @problem = new Problem 1, '/problem/url/' + @problem.element.prepend '
' + + describe 'when the answer has not yet shown', -> + beforeEach -> + @problem.element.removeClass 'showed' + + it 'log the problem_show event', -> + @problem.show() + expect(Logger.log).toHaveBeenCalledWith 'problem_show', problem: 1 + + it 'fetch the answers', -> + spyOn $, 'postWithPrefix' + @problem.show() + expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_show', jasmine.any(Function) + + it 'show the answers', -> + spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback('1_1': 'One', '1_2': 'Two') + @problem.show() + expect($('#answer_1_1')).toHaveHtml 'One' + expect($('#answer_1_2')).toHaveHtml 'Two' + + it 'toggle the show answer button', -> + spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback({}) + @problem.show() + expect($('.show')).toHaveValue 'Hide Answer' + + it 'add the showed class to element', -> + spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback({}) + @problem.show() + expect(@problem.element).toHaveClass 'showed' + + describe 'multiple choice question', -> + beforeEach -> + @problem.element.prepend ''' + + + + + ''' + + it 'set the correct_answer attribute on the choice', -> + spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback('1_1': [2, 3]) + @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' + expect($('label[for="input_1_2_1"]')).not.toHaveAttr 'correct_answer', 'true' + + describe 'when the answers are alreay shown', -> + beforeEach -> + @problem.element.addClass 'showed' + @problem.element.prepend ''' + + ''' + $('#answer_1_1').html('One') + $('#answer_1_2').html('Two') + + it 'hide the answers', -> + @problem.show() + expect($('#answer_1_1')).toHaveHtml '' + expect($('#answer_1_2')).toHaveHtml '' + expect($('label[for="input_1_1_1"]')).not.toHaveAttr 'correct_answer' + + it 'toggle the show answer button', -> + @problem.show() + expect($('.show')).toHaveValue 'Show Answer' + + it 'remove the showed class from element', -> + @problem.show() + expect(@problem.element).not.toHaveClass 'showed' + + describe 'save', -> + beforeEach -> + jasmine.stubRequests() + @problem = new Problem 1, '/problem/url/' + @problem.answers = 'foo=1&bar=2' + + it 'log the problem_save event', -> + @problem.save() + expect(Logger.log).toHaveBeenCalledWith 'problem_save', 'foo=1&bar=2' + + it 'POST to save problem', -> + spyOn $, 'postWithPrefix' + @problem.save() + expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_save', 'foo=1&bar=2', jasmine.any(Function) + + it 'alert to the user', -> + spyOn window, 'alert' + spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'OK') + @problem.save() + expect(window.alert).toHaveBeenCalledWith 'Saved' + + describe 'refreshAnswers', -> + beforeEach -> + @problem = new Problem 1, '/problem/url/' + @problem.element.html ''' +