Answer: One
', 'Answer: Two
'] @@ -423,27 +446,32 @@ describe 'Problem', -> it 'toggle the show answer button, answers are elements', -> answer1 = 'original visual text
' - spyOn(@descriptor, 'getVisualEditor').andCallFake () -> + spyOn(@descriptor, 'getVisualEditor').and.callFake () -> visualEditorStub data = @descriptor.save().data expect(data).toEqual('raw text') it 'Performs link rewriting for static assets when saving', -> visualEditorStub = getContent: () -> 'from visual editor with /c4x/foo/bar/asset/image.jpg' - spyOn(@descriptor, 'getVisualEditor').andCallFake () -> + spyOn(@descriptor, 'getVisualEditor').and.callFake () -> visualEditorStub data = @descriptor.save().data expect(data).toEqual('from visual editor with /static/image.jpg') diff --git a/common/lib/xmodule/xmodule/js/spec/problem/edit_spec.coffee b/common/lib/xmodule/xmodule/js/spec/problem/edit_spec.coffee index 771708d752..b3f7171a4f 100644 --- a/common/lib/xmodule/xmodule/js/spec/problem/edit_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/problem/edit_spec.coffee @@ -24,7 +24,7 @@ describe 'MarkdownEditingDescriptor', -> it 'click on advanced editor should work', -> loadFixtures 'problem-with-markdown.html' @descriptor = new MarkdownEditingDescriptor($('.problem-editor')) - spyOn(@descriptor, 'confirmConversionToXml').andReturn(true) + spyOn(@descriptor, 'confirmConversionToXml').and.returnValue(true) expect(@descriptor.confirmConversionToXml).not.toHaveBeenCalled() e = jasmine.createSpyObj('e', [ 'preventDefault' ]) @descriptor.onShowXMLButton(e) diff --git a/common/lib/xmodule/xmodule/js/spec/tabs/edit.coffee b/common/lib/xmodule/xmodule/js/spec/tabs/edit.coffee index a80aa127a3..ae73009bf3 100644 --- a/common/lib/xmodule/xmodule/js/spec/tabs/edit.coffee +++ b/common/lib/xmodule/xmodule/js/spec/tabs/edit.coffee @@ -14,8 +14,8 @@ describe "TabsEditingDescriptor", -> TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 1 Transcripts', @tab_1_modelUpdate) TabsEditingDescriptor.Model.addOnSwitch(@html_id, 'Tab 1 Transcripts', @tab_1_switch) - spyOn($.fn, 'hide').andCallThrough() - spyOn($.fn, 'show').andCallThrough() + spyOn($.fn, 'hide').and.callThrough() + spyOn($.fn, 'show').and.callThrough() spyOn(TabsEditingDescriptor.Model, 'initialize') spyOn(TabsEditingDescriptor.Model, 'updateValue') @@ -37,11 +37,11 @@ describe "TabsEditingDescriptor", -> expect(@tab_1_switch).toHaveBeenCalled() it "if click on current tab, nothing should happen", -> - spyOn($.fn, 'trigger').andCallThrough() + spyOn($.fn, 'trigger').and.callThrough() currentTab = @descriptor.$tabs.filter('.' + @isCurrent) @descriptor.$tabs.eq(0).trigger("click") expect(@descriptor.$tabs.filter('.' + @isCurrent)).toEqual(currentTab) - expect($.fn.trigger.calls.length).toEqual(1) + expect($.fn.trigger.calls.count()).toEqual(1) it "onSwitch function call", -> @descriptor.$tabs.eq(1).trigger("click") @@ -82,7 +82,7 @@ describe "TabsEditingDescriptor special save cases", -> expect(data).toEqual(null) it "case: no function in model update, but value presented", -> - @tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate').andReturn(1) + @tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate').and.returnValue(1) TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 0 Editor', @tab_0_modelUpdate) @descriptor.$tabs.eq(1).trigger("click") expect(@tab_0_modelUpdate).toHaveBeenCalled() diff --git a/common/lib/xmodule/xmodule/js/spec/video/async_process_spec.js b/common/lib/xmodule/xmodule/js/spec/video/async_process_spec.js index c26ec7c8e7..7fb5bf97d8 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/async_process_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/async_process_spec.js @@ -15,82 +15,66 @@ function (AsyncProcess) { items = getArrayNthLength(1000); describe('AsyncProcess', function () { - it ('Array is processed successfully', function () { + it ('Array is processed successfully', function (done) { var processedArray, expectedArray = getArrayNthLength(1000, 2), process = function (item) { return 2 * item; }; - runs(function () { - AsyncProcess.array(items, process).done(function (result) { - processedArray = result; - }); + AsyncProcess.array(items, process).done(function (result) { + processedArray = result; }); - waitsFor(function () { + jasmine.waitUntil(function () { return processedArray; - }, 'Array processing takes too much time', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(processedArray).toEqual(expectedArray); - }); + }).always(done); }); - it ('If non-array is passed, error callback is called', function () { + it ('If non-array is passed, error callback is called', function (done) { var isError, process = function () {}; - runs(function () { - AsyncProcess.array('string', process).fail(function () { - isError = true; - }); + AsyncProcess.array('string', process).fail(function () { + isError = true; }); - waitsFor(function () { + jasmine.waitUntil(function () { return isError; - }, 'Error callback wasn\'t called', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(isError).toBeTruthy(); - }); + }).always(done); }); - it ('If an empty array is passed, returns initial array', function () { + it ('If an empty array is passed, returns initial array', function (done) { var processedArray, process = function () {}; - runs(function () { - AsyncProcess.array([], process).done(function (result) { - processedArray = result; - }); + AsyncProcess.array([], process).done(function (result) { + processedArray = result; }); - waitsFor(function () { + jasmine.waitUntil(function () { return processedArray; - }, 'Array processing takes too much time', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(processedArray).toEqual([]); - }); + }).always(done); }); - it ('If no process function passed, returns initial array', function () { + it ('If no process function passed, returns initial array', function (done) { var processedArray; - runs(function () { - AsyncProcess.array(items).done(function (result) { - processedArray = result; - }); + AsyncProcess.array(items).done(function (result) { + processedArray = result; }); - waitsFor(function () { + jasmine.waitUntil(function () { return processedArray; - }, 'Array processing takes too much time', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(processedArray).toEqual(items); - }); + }).always(done); }); }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/events_spec.js b/common/lib/xmodule/xmodule/js/spec/video/events_spec.js index 437577c7dd..8f85970551 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/events_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/events_spec.js @@ -7,9 +7,7 @@ oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine .createSpy('onTouchBasedDevice') - .andReturn(null); - - jasmine.stubRequests(); + .and.returnValue(null); state = jasmine.initializePlayer(); @@ -20,26 +18,23 @@ $('source').remove(); window.onTouchBasedDevice = oldOTBD; state.storage.clear(); + state.videoPlayer.destroy(); }); - it('initialize', function () { - waitsFor(function () { + it('initialize', function (done) { + jasmine.waitUntil(function () { return state.el.hasClass('is-initialized'); - }, 'Player is not initialized.', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect('initialize').not.toHaveBeenTriggeredOn('.video'); - }); + }).always(done); }); - it('ready', function () { - waitsFor(function () { + it('ready', function (done) { + jasmine.waitUntil(function () { return state.el.hasClass('is-initialized'); - }, 'Player is not initialized.', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect('ready').not.toHaveBeenTriggeredOn('.video'); - }); + }).always(done); }); it('play', function () { @@ -86,9 +81,7 @@ oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine .createSpy('onTouchBasedDevice') - .andReturn(null); - - jasmine.stubRequests(); + .and.returnValue(null); state = jasmine.initializePlayerYouTube(); }); @@ -96,6 +89,8 @@ afterEach(function () { $('source').remove(); window.onTouchBasedDevice = oldOTBD; + state.storage.clear(); + state.videoPlayer.destroy(); }); it('qualitychange', function () { diff --git a/common/lib/xmodule/xmodule/js/spec/video/general_spec.js b/common/lib/xmodule/xmodule/js/spec/video/general_spec.js index f9c0eabf2d..cc188d1c34 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/general_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/general_spec.js @@ -2,26 +2,27 @@ describe('Video', function () { var oldOTBD, state; - beforeEach(function () { - jasmine.stubRequests(); - }); - afterEach(function () { $('source').remove(); window.VideoState = {}; window.VideoState.id = {}; + window.YT = jasmine.YT; }); describe('constructor', function () { describe('YT', function () { beforeEach(function () { loadFixtures('video.html'); - $.cookie.andReturn('0.50'); - this.state = jasmine.initializePlayerYouTube('video_html5.html'); + $.cookie.and.returnValue('0.50'); }); describe('by default', function () { + beforeEach(function () { + this.state = jasmine.initializePlayerYouTube('video_html5.html'); + }); + afterEach(function () { + this.state.storage.clear(); this.state.videoPlayer.destroy(); }); @@ -30,7 +31,7 @@ }); it('set the elements', function () { - expect(this.state.el).toBe('#video_id'); + expect(this.state.el).toEqual($('#video_id')); }); it('parse the videos', function () { @@ -55,13 +56,13 @@ var state; beforeEach(function () { - $.cookie.andReturn('0.75'); + $.cookie.and.returnValue('0.75'); state = jasmine.initializePlayer('video_html5.html'); }); afterEach(function () { + state.storage.clear(); state.videoPlayer.destroy(); - state = undefined; }); describe('by default', function () { @@ -70,7 +71,7 @@ }); it('set the elements', function () { - expect(state.el).toBe('#video_id'); + expect(state.el).toEqual($('#video_id')); }); it('doesn\'t have `videos` dictionary', function () { @@ -101,35 +102,34 @@ }); describe('YouTube API is not loaded', function () { + var state; beforeEach(function () { window.YT = undefined; state = jasmine.initializePlayerYouTube(); - }) + }); afterEach(function () { + state.storage.clear(); state.videoPlayer.destroy(); }); - it('callback, to be called after YouTube API loads, exists and is called', function () { - waitsFor(function () { - return state.youtubeApiAvailable === true; - }, 'YouTube API is loaded', 3000); - + it('callback, to be called after YouTube API loads, exists and is called', function (done) { window.YT = jasmine.YT; - // Call the callback that must be called when YouTube API is // loaded. By specification. window.onYouTubeIframeAPIReady(); - - runs(function () { + jasmine.waitUntil(function () { + return state.youtubeApiAvailable === true; + }).done(function(){ // If YouTube API is not loaded, then the code will should create // a global callback that will be called by API once it is loaded. expect(window.onYouTubeIframeAPIReady).not.toBeUndefined(); - }); + }).always(done); }); }); describe('checking start and end times', function () { + var state; var miniTestSuite = [ { itDescription: 'both times are proper', @@ -159,6 +159,7 @@ ]; afterEach(function () { + state.storage.clear(); state.videoPlayer.destroy(); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js b/common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js index 2f9126cd8c..be4929df27 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js @@ -1,17 +1,19 @@ (function (undefined) { describe('Video HTML5Video', function () { + var STATUS = window.STATUS; var state, oldOTBD, playbackRates = [0.75, 1.0, 1.25, 1.5]; beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); + }); afterEach(function () { state.storage.clear(); state.videoPlayer.destroy(); - $.fn.scrollTo.reset(); + $.fn.scrollTo.calls.reset(); $('source').remove(); window.onTouchBasedDevice = oldOTBD; }); @@ -25,13 +27,13 @@ describe('events:', function () { beforeEach(function () { - spyOn(state.videoPlayer.player, 'callStateChangeCallback').andCallThrough(); + spyOn(state.videoPlayer.player, 'callStateChangeCallback').and.callThrough(); }); describe('[click]', function () { describe('when player is paused', function () { beforeEach(function () { - spyOn(state.videoPlayer.player.video, 'play').andCallThrough(); + spyOn(state.videoPlayer.player.video, 'play').and.callThrough(); state.videoPlayer.player.playerState = STATUS.PAUSED; $(state.videoPlayer.player.videoEl).trigger('click'); }); @@ -40,32 +42,25 @@ expect(state.videoPlayer.player.video.play).toHaveBeenCalled(); }); - it('player state was changed', function () { - waitsFor(function () { - return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED; - }, 'Player state should be changed', WAIT_TIMEOUT); - - runs(function () { - expect(state.videoPlayer.player.getPlayerState()) - .toBe(STATUS.PLAYING); - }); + it('player state was changed', function (done) { + jasmine.waitUntil(function () { + return state.videoPlayer.player.getPlayerState() === STATUS.PLAYING; + }).always(done); }); - it('callback was not called', function () { - waitsFor(function () { + // Flaky. Checking the parameters of calls to onStateChange() will likely be more reliable. + xit('callback was not called', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED; - }, 'Player state should be changed', WAIT_TIMEOUT); - - runs(function () { - expect(state.videoPlayer.player.callStateChangeCallback) - .not.toHaveBeenCalled(); - }); + }).then(function () { + expect(state.videoPlayer.player.callStateChangeCallback).not.toHaveBeenCalled(); + }).always(done); }); }); describe('[player is playing]', function () { beforeEach(function () { - spyOn(state.videoPlayer.player.video, 'pause').andCallThrough(); + spyOn(state.videoPlayer.player.video, 'pause').and.callThrough(); state.videoPlayer.player.playerState = STATUS.PLAYING; $(state.videoPlayer.player.videoEl).trigger('click'); }); @@ -74,33 +69,29 @@ expect(state.videoPlayer.player.video.pause).toHaveBeenCalled(); }); - it('player state was changed', function () { - waitsFor(function () { + it('player state was changed', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING; - }, 'Player state should be changed', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoPlayer.player.getPlayerState()) .toBe(STATUS.PAUSED); - }); + }).always(done); }); - it('callback was not called', function () { - waitsFor(function () { + it('callback was not called', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING; - }, 'Player state should be changed', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoPlayer.player.callStateChangeCallback) .not.toHaveBeenCalled(); - }); + }).always(done); }); }); }); describe('[play]', function () { beforeEach(function () { - spyOn(state.videoPlayer.player.video, 'play').andCallThrough(); + spyOn(state.videoPlayer.player.video, 'play').and.callThrough(); state.videoPlayer.player.playerState = STATUS.PAUSED; state.videoPlayer.player.playVideo(); }); @@ -110,37 +101,35 @@ }); - it('player state was changed', function () { - waitsFor(function () { + it('player state was changed', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED; - }, 'Player state should be changed', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoPlayer.player.getPlayerState()) .toBe(STATUS.BUFFERING); - }); + }).always(done); }); - it('callback was called', function () { - waitsFor(function () { + it('callback was called', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.PAUSED; - }, 'Player state should be changed', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoPlayer.player.callStateChangeCallback) .toHaveBeenCalled(); - }); + }).always(done); }); }); describe('[pause]', function () { - beforeEach(function () { - spyOn(state.videoPlayer.player.video, 'pause').andCallThrough(); + beforeEach(function (done) { + spyOn(state.videoPlayer.player.video, 'pause').and.callThrough(); state.videoPlayer.player.playerState = STATUS.UNSTARTED; state.videoPlayer.player.playVideo(); - waitsFor(function () { + + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.UNSTARTED; - }, 'Video never started playing', WAIT_TIMEOUT); + }).done(done); + state.videoPlayer.player.pauseVideo(); }); @@ -148,59 +137,54 @@ expect(state.videoPlayer.player.video.pause).toHaveBeenCalled(); }); - it('player state was changed', function () { - waitsFor(function () { + it('player state was changed', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING; - }, 'Player state should be changed', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoPlayer.player.getPlayerState()) .toBe(STATUS.PAUSED); - }); + }).always(done); }); - it('callback was called', function () { - waitsFor(function () { + it('callback was called', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.PLAYING; - }, 'Player state should be changed', WAIT_TIMEOUT); - runs(function () { + }).then(function () { expect(state.videoPlayer.player.callStateChangeCallback) .toHaveBeenCalled(); - }); + }).always(done); }); }); describe('[loadedmetadata]', function () { it( 'player state was changed, start/end was defined, ' + - 'onReady called', function () + 'onReady called', function (done) { - waitsFor(function () { + jasmine.fireEvent(state.videoPlayer.player.video, 'loadedmetadata'); + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.UNSTARTED; - }, 'Video cannot be played', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoPlayer.player.getPlayerState()) .toBe(STATUS.PAUSED); expect(state.videoPlayer.player.video.currentTime).toBe(0); expect(state.videoPlayer.player.config.events.onReady) .toHaveBeenCalled(); - }); + }).always(done); }); }); describe('[ended]', function () { - beforeEach(function () { - waitsFor(function () { + beforeEach(function (done) { + state.videoPlayer.player.playVideo(); + jasmine.waitUntil(function () { return state.videoPlayer.player.getPlayerState() !== STATUS.UNSTARTED; - }, 'Video cannot be played', WAIT_TIMEOUT); + }).done(done); }); it('player state was changed', function () { - runs(function () { - jasmine.fireEvent(state.videoPlayer.player.video, 'ended'); - expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.ENDED); - }); + jasmine.fireEvent(state.videoPlayer.player.video, 'ended'); + expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.ENDED); }); it('callback was called', function () { @@ -215,98 +199,90 @@ var volume, seek, duration, playbackRate; beforeEach(function () { - waitsFor(function () { - volume = state.videoPlayer.player.video.volume; - seek = state.videoPlayer.player.video.currentTime; - return state.videoPlayer.player.playerState === STATUS.PAUSED; - }, 'Video cannot be played', WAIT_TIMEOUT); + volume = state.videoPlayer.player.video.volume; }); it('pauseVideo', function () { - runs(function () { - spyOn(state.videoPlayer.player.video, 'pause').andCallThrough(); - state.videoPlayer.player.pauseVideo(); - expect(state.videoPlayer.player.video.pause).toHaveBeenCalled(); - }); + spyOn(state.videoPlayer.player.video, 'pause').and.callThrough(); + state.videoPlayer.player.pauseVideo(); + expect(state.videoPlayer.player.video.pause).toHaveBeenCalled(); }); describe('seekTo', function () { - it('set new correct value', function () { - runs(function () { + it('set new correct value', function (done) { + state.videoPlayer.player.playVideo(); + jasmine.waitUntil(function () { + return state.videoPlayer.player.getPlayerState() === STATUS.PLAYING; + }).then(function() { state.videoPlayer.player.seekTo(2); expect(state.videoPlayer.player.getCurrentTime()).toBe(2); - }); + }).done(done); }); it('set new inccorrect values', function () { - runs(function () { - state.videoPlayer.player.seekTo(-50); - expect(state.videoPlayer.player.getCurrentTime()).toBe(seek); - state.videoPlayer.player.seekTo('5'); - expect(state.videoPlayer.player.getCurrentTime()).toBe(seek); - state.videoPlayer.player.seekTo(500000); - expect(state.videoPlayer.player.getCurrentTime()).toBe(seek); - }); + var seek = state.videoPlayer.player.video.currentTime; + state.videoPlayer.player.seekTo(-50); + expect(state.videoPlayer.player.getCurrentTime()).toBe(seek); + state.videoPlayer.player.seekTo('5'); + expect(state.videoPlayer.player.getCurrentTime()).toBe(seek); + state.videoPlayer.player.seekTo(500000); + expect(state.videoPlayer.player.getCurrentTime()).toBe(seek); }); }); describe('setVolume', function () { it('set new correct value', function () { - runs(function () { - state.videoPlayer.player.setVolume(50); - expect(state.videoPlayer.player.getVolume()).toBe(50 * 0.01); - }); + state.videoPlayer.player.setVolume(50); + expect(state.videoPlayer.player.getVolume()).toBe(50 * 0.01); }); it('set new incorrect values', function () { - runs(function () { - state.videoPlayer.player.setVolume(-50); - expect(state.videoPlayer.player.getVolume()).toBe(volume); - state.videoPlayer.player.setVolume('5'); - expect(state.videoPlayer.player.getVolume()).toBe(volume); - state.videoPlayer.player.setVolume(500000); - expect(state.videoPlayer.player.getVolume()).toBe(volume); - }); - }); - }); - - it('getCurrentTime', function () { - runs(function () { - state.videoPlayer.player.video.currentTime = 3; - expect(state.videoPlayer.player.getCurrentTime()) - .toBe(state.videoPlayer.player.video.currentTime); - }); - }); - - it('playVideo', function () { - runs(function () { - spyOn(state.videoPlayer.player.video, 'play').andCallThrough(); - state.videoPlayer.player.playVideo(); - expect(state.videoPlayer.player.video.play).toHaveBeenCalled(); - }); - }); - - it('getPlayerState', function () { - runs(function () { - state.videoPlayer.player.playerState = STATUS.PLAYING; - expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.PLAYING); - state.videoPlayer.player.playerState = STATUS.ENDED; - expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.ENDED); - }); - }); - - it('getVolume', function () { - runs(function () { - volume = state.videoPlayer.player.video.volume = 0.5; + state.videoPlayer.player.setVolume(-50); + expect(state.videoPlayer.player.getVolume()).toBe(volume); + state.videoPlayer.player.setVolume('5'); + expect(state.videoPlayer.player.getVolume()).toBe(volume); + state.videoPlayer.player.setVolume(500000); expect(state.videoPlayer.player.getVolume()).toBe(volume); }); }); - it('getDuration', function () { - runs(function () { + it('getCurrentTime', function (done) { + state.videoPlayer.player.playVideo(); + jasmine.waitUntil(function () { + return state.videoPlayer.player.getPlayerState() === STATUS.PLAYING; + }).then(function() { + state.videoPlayer.player.video.currentTime = 3; + expect(state.videoPlayer.player.getCurrentTime()) + .toBe(state.videoPlayer.player.video.currentTime); + }).done(done); + }); + + it('playVideo', function () { + spyOn(state.videoPlayer.player.video, 'play').and.callThrough(); + state.videoPlayer.player.playVideo(); + expect(state.videoPlayer.player.video.play).toHaveBeenCalled(); + }); + + it('getPlayerState', function () { + state.videoPlayer.player.playerState = STATUS.PLAYING; + expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.PLAYING); + state.videoPlayer.player.playerState = STATUS.ENDED; + expect(state.videoPlayer.player.getPlayerState()).toBe(STATUS.ENDED); + }); + + it('getVolume', function () { + volume = state.videoPlayer.player.video.volume = 0.5; + expect(state.videoPlayer.player.getVolume()).toBe(volume); + }); + + it('getDuration', function (done) { + state.videoPlayer.player.playVideo(); + jasmine.waitUntil(function () { + return state.videoPlayer.player.getPlayerState() === STATUS.PLAYING; + }).then(function () { duration = state.videoPlayer.player.video.duration; expect(state.videoPlayer.player.getDuration()).toBe(duration); - }); + }).always(done); }); describe('setPlaybackRate', function () { @@ -333,18 +309,21 @@ .toEqual(playbackRates); }); - it('_getLogs', function () { - runs(function () { + it('_getLogs', function (done) { + state.videoPlayer.player.playVideo(); + jasmine.waitUntil(function () { + return state.videoPlayer.player.getPlayerState() === STATUS.PLAYING; + }).then(function() { var logs = state.videoPlayer.player._getLogs(); expect(logs).toEqual(jasmine.any(Array)); expect(logs.length).toBeGreaterThan(0); - }); + }).done(done); }); }); }); it('native controls are used on iPhone', function () { - window.onTouchBasedDevice.andReturn(['iPhone']); + window.onTouchBasedDevice.and.returnValue(['iPhone']); state = jasmine.initializePlayer('video_html5.html'); diff --git a/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js b/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js index 0404005144..cc26892bd7 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/initialize_spec.js @@ -82,7 +82,7 @@ function (Initialize) { '1.50': 'videoId' }, youtubeId: Initialize.prototype.youtubeId, - isFlashMode: jasmine.createSpy().andReturn(false) + isFlashMode: jasmine.createSpy().and.returnValue(false) }; }); @@ -100,7 +100,7 @@ function (Initialize) { it('returns duration for current video', function () { var expected; - state.isFlashMode.andReturn(true); + state.isFlashMode.and.returnValue(true); expected = Initialize.prototype.getDuration.call(state); expect(expected).toEqual(100); @@ -110,7 +110,7 @@ function (Initialize) { it(msg, function () { var expected; - state.isFlashMode.andReturn(true); + state.isFlashMode.and.returnValue(true); state.speed = '2.0'; expected = Initialize.prototype.getDuration.call(state); @@ -128,7 +128,7 @@ function (Initialize) { '1.0': 'cogebirgzzM', '1.50': 'abcdefghijkl' }, - isFlashMode: jasmine.createSpy().andReturn(false) + isFlashMode: jasmine.createSpy().and.returnValue(false) }; }); @@ -148,7 +148,7 @@ function (Initialize) { it('return the video id for current speed', function () { var expected; - state.isFlashMode.andReturn(true); + state.isFlashMode.and.returnValue(true); expected = Initialize.prototype.youtubeId.call(state); expect(expected).toEqual('abcdefghijkl'); @@ -279,7 +279,7 @@ function (Initialize) { describe('isFlashMode', function () { it('returns `true` if player in `flash` mode', function () { var state = { - getPlayerMode: jasmine.createSpy().andReturn('flash'), + getPlayerMode: jasmine.createSpy().and.returnValue('flash'), }, isFlashMode = Initialize.prototype.isFlashMode, actual = isFlashMode.call(state); @@ -289,7 +289,7 @@ function (Initialize) { it('returns `false` if player is not in `flash` mode', function () { var state = { - getPlayerMode: jasmine.createSpy().andReturn('html5'), + getPlayerMode: jasmine.createSpy().and.returnValue('html5'), }, isFlashMode = Initialize.prototype.isFlashMode, actual = isFlashMode.call(state); @@ -301,7 +301,7 @@ function (Initialize) { describe('isHtml5Mode', function () { it('returns `true` if player in `html5` mode', function () { var state = { - getPlayerMode: jasmine.createSpy().andReturn('html5'), + getPlayerMode: jasmine.createSpy().and.returnValue('html5'), }, isHtml5Mode = Initialize.prototype.isHtml5Mode, actual = isHtml5Mode.call(state); @@ -311,7 +311,7 @@ function (Initialize) { it('returns `false` if player is not in `html5` mode', function () { var state = { - getPlayerMode: jasmine.createSpy().andReturn('flash'), + getPlayerMode: jasmine.createSpy().and.returnValue('flash'), }, isHtml5Mode = Initialize.prototype.isHtml5Mode, actual = isHtml5Mode.call(state); diff --git a/common/lib/xmodule/xmodule/js/spec/video/resizer_spec.js b/common/lib/xmodule/xmodule/js/spec/video/resizer_spec.js index 0064e71a42..23e149e824 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/resizer_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/resizer_spec.js @@ -139,7 +139,7 @@ function (Resizer) { .align() .alignByHeightOnly(); - expect(spiesList[0].calls.length).toEqual(1); + expect(spiesList[0].calls.count()).toEqual(1); }); it('all callbacks are removed', function () { @@ -180,7 +180,7 @@ function (Resizer) { resizer.callbacks[methodName](arg); expect(console.error).toHaveBeenCalledWith(errorMessage); //reset spy - console.log.reset(); + console.log.calls.reset(); }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_accessible_menu_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_accessible_menu_spec.js index feae0e58f3..e80c3be79b 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_accessible_menu_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_accessible_menu_spec.js @@ -101,7 +101,7 @@ menuList = container.children('ol.a11y-menu-list'); menuItems = menuList.children('li.a11y-menu-item'); menuItemsLinks = menuItems.children('a.a11y-menu-item-link'); - spyOn($.fn, 'focus').andCallThrough(); + spyOn($.fn, 'focus').and.callThrough(); }); it('open/close the menu on mouseenter/mouseleave', function () { @@ -173,7 +173,7 @@ } // Test if each element has been called twice. - expect($.fn.focus.calls.length) + expect($.fn.focus.calls.count()) .toEqual(2*menuItemsLinks.length+1); }); @@ -258,7 +258,7 @@ beforeEach(function () { state = jasmine.initializePlayer(); state.videoSpeedControl.setSpeed(1.0); - spyOn(state.videoPlayer, 'onSpeedChange').andCallThrough(); + spyOn(state.videoPlayer, 'onSpeedChange').and.callThrough(); $('li[data-speed="0.75"] .speed-link').click(); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_bumper_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_bumper_spec.js index 0a355e918d..373f3e5274 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_bumper_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_bumper_spec.js @@ -3,19 +3,19 @@ describe('VideoBumper', function () { var state, oldOTBD, waitForPlaying; - waitForPlaying = function (state) { - waitsFor(function () { + waitForPlaying = function (state, done) { + jasmine.waitUntil(function () { return state.el.hasClass('is-playing'); - }, 'Player is not playing.', WAIT_TIMEOUT); + }).done(done); }; beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); state = jasmine.initializePlayer('video_with_bumper.html'); $('.poster .btn-play').click(); - jasmine.Clock.useMock(); + jasmine.clock().install(); }); afterEach(function () { @@ -28,45 +28,46 @@ state.videoPlayer.destroy(); } window.onTouchBasedDevice = oldOTBD; + jasmine.clock().uninstall(); }); it('can render the bumper video', function () { expect($('.is-bumper')).toExist(); }); - it('can show the main video on error', function () { + it('can show the main video on error', function (done) { state.el.trigger('error'); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect($('.is-bumper')).not.toExist(); - waitForPlaying(state); + waitForPlaying(state, done); }); - it('can show the main video once bumper ends', function () { + it('can show the main video once bumper ends', function (done) { state.el.trigger('ended'); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect($('.is-bumper')).not.toExist(); - waitForPlaying(state); + waitForPlaying(state, done); }); - it('can show the main video on skip', function () { + it('can show the main video on skip', function (done) { state.bumperState.videoBumper.skip(); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect($('.is-bumper')).not.toExist(); - waitForPlaying(state); + waitForPlaying(state, done); }); - it('can stop the bumper video playing if it is too long', function () { + it('can stop the bumper video playing if it is too long', function (done) { state.el.trigger('timeupdate', [state.bumperState.videoBumper.maxBumperDuration + 1]); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect($('.is-bumper')).not.toExist(); - waitForPlaying(state); + waitForPlaying(state, done); }); it('can save appropriate states correctly on ended', function () { var saveState = jasmine.createSpy('saveState'); state.bumperState.videoSaveStatePlugin.saveState = saveState; state.el.trigger('ended'); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect(saveState).toHaveBeenCalledWith(true, { bumper_last_view_date: true}); }); @@ -76,7 +77,7 @@ state.bumperState.videoSaveStatePlugin.saveState = saveState; state.bumperState.videoBumper.skip(); expect(state.storage.getItem('isBumperShown')).toBeTruthy(); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect(saveState).toHaveBeenCalledWith(true, { bumper_last_view_date: true}); }); @@ -86,7 +87,7 @@ state.bumperState.videoSaveStatePlugin.saveState = saveState; state.el.trigger('error'); expect(state.storage.getItem('isBumperShown')).toBeTruthy(); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect(saveState).toHaveBeenCalledWith(true, { bumper_last_view_date: true}); }); @@ -96,7 +97,7 @@ state.bumperState.videoSaveStatePlugin.saveState = saveState; state.bumperState.videoBumper.skipAndDoNotShowAgain(); expect(state.storage.getItem('isBumperShown')).toBeTruthy(); - jasmine.Clock.tick(20); + jasmine.clock().tick(20); expect(saveState).toHaveBeenCalledWith(true, { bumper_last_view_date: true, bumper_do_not_show_again: true}); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js index 95bb6a879c..7442fdd8ff 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js @@ -1,13 +1,16 @@ (function (undefined) { describe('VideoCaption', function () { var state, oldOTBD; + var parseIntAttribute = function (element, attrName) { + return parseInt(element.attr(attrName)); + }; beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); - $.fn.scrollTo.reset(); + $.fn.scrollTo.calls.reset(); }); afterEach(function () { @@ -15,7 +18,7 @@ // had before. Removing of `source` tag, not `video` tag, stops // loading video source and clears the memory. $('source').remove(); - $.fn.scrollTo.reset(); + $.fn.scrollTo.calls.reset(); state.storage.clear(); state.videoPlayer.destroy(); @@ -27,17 +30,17 @@ describe('always', function () { beforeEach(function () { - spyOn($, 'ajaxWithPrefix').andCallThrough(); + spyOn($, 'ajaxWithPrefix').and.callThrough(); }); it('create the transcript element', function () { state = jasmine.initializePlayer(); - expect($('.video')).toContain('.subtitles'); + expect($('.video')).toContainElement('.subtitles'); }); it('add transcript control to video player', function () { state = jasmine.initializePlayer(); - expect($('.video')).toContain('.toggle-transcript'); + expect($('.video')).toContainElement('.toggle-transcript'); }); it('add ARIA attributes to transcript control', function () { @@ -50,20 +53,16 @@ it('adds the captioning control to the video player', function() { state = jasmine.initializePlayer(); - expect($('.video')).toContain('.toggle-captions'); - expect($('.video')).toContain('.closed-captions'); + expect($('.video')).toContainElement('.toggle-captions'); + expect($('.video')).toContainElement('.closed-captions'); }); - it('fetch the transcript in HTML5 mode', function () { - runs(function () { - state = jasmine.initializePlayer(); - }); + it('fetch the transcript in HTML5 mode', function (done) { + state = jasmine.initializePlayer(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.loaded; - }, 'Expect transcript to be loaded.', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect($.ajaxWithPrefix).toHaveBeenCalledWith({ url: '/transcript/translation/en', notifyOnError: false, @@ -71,23 +70,19 @@ success: jasmine.any(Function), error: jasmine.any(Function) }); - expect($.ajaxWithPrefix.mostRecentCall.args[0].data) + expect($.ajaxWithPrefix.calls.mostRecent().args[0].data) .toBeUndefined(); - }); + }).always(done); }); - it('fetch the transcript in Flash mode', function () { - runs(function () { - state = jasmine.initializePlayerYouTube(); - spyOn(state, 'isFlashMode').andReturn(true); - state.videoCaption.fetchCaption(); - }); + it('fetch the transcript in Flash mode', function (done) { + state = jasmine.initializePlayerYouTube(); + spyOn(state, 'isFlashMode').and.returnValue(true); + state.videoCaption.fetchCaption(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.loaded; - }, 'Expect transcript to be loaded.', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect($.ajaxWithPrefix).toHaveBeenCalledWith({ url: '/transcript/translation/en', notifyOnError: false, @@ -95,23 +90,19 @@ success: jasmine.any(Function), error: jasmine.any(Function) }); - expect($.ajaxWithPrefix.mostRecentCall.args[0].data) + expect($.ajaxWithPrefix.calls.mostRecent().args[0].data) .toEqual({ videoId: 'cogebirgzzM' }); - }); + }).always(done); }); - it('fetch the transcript in Youtube mode', function () { - runs(function () { - state = jasmine.initializePlayerYouTube(); - }); + it('fetch the transcript in Youtube mode', function (done) { + state = jasmine.initializePlayerYouTube(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.loaded; - }, 'Expect transcript to be loaded.', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect($.ajaxWithPrefix).toHaveBeenCalledWith({ url: '/transcript/translation/en', notifyOnError: false, @@ -119,11 +110,11 @@ success: jasmine.any(Function), error: jasmine.any(Function) }); - expect($.ajaxWithPrefix.mostRecentCall.args[0].data) + expect($.ajaxWithPrefix.calls.mostRecent().args[0].data) .toEqual({ videoId: 'cogebirgzzM' }); - }); + }).always(done); }); it('bind the mouse movement', function () { @@ -148,7 +139,7 @@ state = jasmine.initializePlayer(); var plugin = state.videoCaption; - spyOn($.fn, 'off').andCallThrough(); + spyOn($.fn, 'off').and.callThrough(); state.videoCaption.destroy(); expect(state.videoCaption).toBeUndefined(); @@ -316,104 +307,90 @@ }); describe('when on a non touch-based device', function () { - beforeEach(function () { - runs(function () { - state = jasmine.initializePlayer(); - }); + beforeEach(function (done) { + state = jasmine.initializePlayer(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); + }).then(done); }); it('render the transcript', function () { - runs(function () { - var captionsData = jasmine.stubbedCaption, - items = $('.subtitles li[data-index]'); + var captionsData = jasmine.stubbedCaption, + items = $('.subtitles li[data-index]'); - _.each(captionsData.text, function (text, index) { - var item = items.eq(index); + _.each(captionsData.text, function (text, index) { + var item = items.eq(index); - expect(item).toHaveData('index', index); - expect(item).toHaveData( - 'start', captionsData.start[index] - ); - expect(item).toHaveAttr('tabindex', 0); - expect(item).toHaveText(text); - }); + expect(parseIntAttribute(item, 'data-index')).toEqual(index); + expect(parseIntAttribute(item, 'data-start')).toEqual(captionsData.start[index]); + expect(item.attr('tabindex')).toEqual(0); + expect(item.text().trim()).toEqual(captionsData.text[index]); }); }); it('add a padding element to transcript', function () { - runs(function () { - expect($('.subtitles li:first').hasClass('spacing')) - .toBe(true); - expect($('.subtitles li:last').hasClass('spacing')) - .toBe(true); - }); + expect($('.subtitles li:first').hasClass('spacing')) + .toBe(true); + expect($('.subtitles li:last').hasClass('spacing')) + .toBe(true); }); it('bind all the transcript link', function () { - runs(function () { - var handlerList = ['captionMouseOverOut', 'captionClick', - 'captionMouseDown', 'captionFocus', 'captionBlur', - 'captionKeyDown' - ]; + var handlerList = ['captionMouseOverOut', 'captionClick', + 'captionMouseDown', 'captionFocus', 'captionBlur', + 'captionKeyDown' + ]; - $.each(handlerList, function(index, handler) { - spyOn(state.videoCaption, handler); - }); - $('.subtitles li[data-index]').each( - function (index, link) { + $.each(handlerList, function(index, handler) { + spyOn(state.videoCaption, handler); + }); + $('.subtitles li[data-index]').each( + function (index, link) { - $(link).trigger('mouseover'); - expect(state.videoCaption.captionMouseOverOut).toHaveBeenCalled(); + $(link).trigger('mouseover'); + expect(state.videoCaption.captionMouseOverOut).toHaveBeenCalled(); - state.videoCaption.captionMouseOverOut.reset(); - $(link).trigger('mouseout'); - expect(state.videoCaption.captionMouseOverOut).toHaveBeenCalled(); + state.videoCaption.captionMouseOverOut.calls.reset(); + $(link).trigger('mouseout'); + expect(state.videoCaption.captionMouseOverOut).toHaveBeenCalled(); - $(this).click(); - expect(state.videoCaption.captionClick).toHaveBeenCalled(); + $(this).click(); + expect(state.videoCaption.captionClick).toHaveBeenCalled(); - $(this).trigger('mousedown'); - expect(state.videoCaption.captionMouseDown).toHaveBeenCalled(); + $(this).trigger('mousedown'); + expect(state.videoCaption.captionMouseDown).toHaveBeenCalled(); - $(this).trigger('focus'); - expect(state.videoCaption.captionFocus).toHaveBeenCalled(); + $(this).trigger('focus'); + expect(state.videoCaption.captionFocus).toHaveBeenCalled(); - $(this).trigger('blur'); - expect(state.videoCaption.captionBlur).toHaveBeenCalled(); + $(this).trigger('blur'); + expect(state.videoCaption.captionBlur).toHaveBeenCalled(); - $(this).trigger('keydown'); - expect(state.videoCaption.captionKeyDown).toHaveBeenCalled(); - }); + $(this).trigger('keydown'); + expect(state.videoCaption.captionKeyDown).toHaveBeenCalled(); }); }); - it('set rendered to true', function () { - runs(function () { - state = jasmine.initializePlayer(); - }); + it('set rendered to true', function (done) { + state = jasmine.initializePlayer(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoCaption.rendered).toBeTruthy(); - }); + }).always(done); }); }); describe('when on a touch-based device', function () { beforeEach(function () { - window.onTouchBasedDevice.andReturn(['iPad']); + window.onTouchBasedDevice.and.returnValue(['iPad']); state = jasmine.initializePlayer(); - $.fn.scrollTo.reset(); + $.fn.scrollTo.calls.reset(); }); it('show explanation message', function () { @@ -422,30 +399,24 @@ ); }); - it('show transcript on play', function () { - runs(function () { - state.el.trigger('play'); - }); + it('show transcript on play', function (done) { + state.el.trigger('play'); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { var captionsData = jasmine.stubbedCaption, items = $('.subtitles li[data-index]'); _.each(captionsData.text, function (text, index) { var item = items.eq(index); - expect(item).toHaveData('index', index); - expect(item).toHaveData( - 'start', captionsData.start[index] - ); - expect(item).toHaveAttr('tabindex', 0); - expect(item).toHaveText(text); + expect(parseIntAttribute(item, 'data-index')).toEqual(index); + expect(parseIntAttribute(item, 'data-start')).toEqual(captionsData.start[index]); + expect(item.attr('tabindex')).toEqual(0); + expect(item.text().trim()).toEqual(text); }); - }); + }).always(done); }); it('does not set rendered to true', function () { @@ -467,62 +438,58 @@ }); }); + var originalClearTimeout; + describe('mouse movement', function () { - beforeEach(function () { - jasmine.Clock.useMock(); - spyOn(window, 'clearTimeout'); - - runs(function () { - state = jasmine.initializePlayer(); - jasmine.Clock.tick(50); - }); - - waitsFor(function () { + beforeEach(function (done) { + jasmine.clock().install(); + state = jasmine.initializePlayer(); + jasmine.clock().tick(50); + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); + }).then(done); + + // Why we can't use spyOn(): https://github.com/jasmine/jasmine/issues/826 + originalClearTimeout = window.clearTimeout; + window.clearTimeout = jasmine.createSpy().and.callFake(originalClearTimeout); + }); + + afterEach(function () { + window.clearTimeout = originalClearTimeout; + jasmine.clock().uninstall(); }); describe('when cursor is outside of the transcript box', function () { it('does not set freezing timeout', function () { - runs(function () { - expect(state.videoCaption.frozen).toBeFalsy(); - }); + expect(state.videoCaption.frozen).toBeFalsy(); }); }); describe('when cursor is in the transcript box', function () { beforeEach(function () { spyOn(state.videoCaption, 'onMouseLeave'); - runs(function () { - $(window).trigger(jQuery.Event('mousemove')); - jasmine.Clock.tick(state.config.captionsFreezeTime); - $('.subtitles-menu').trigger(jQuery.Event('mouseenter')); - jasmine.Clock.tick(state.config.captionsFreezeTime); - }); + $(window).trigger(jQuery.Event('mousemove')); + jasmine.clock().tick(state.config.captionsFreezeTime); + $('.subtitles-menu').trigger(jQuery.Event('mouseenter')); + jasmine.clock().tick(state.config.captionsFreezeTime); }); it('set the freezing timeout', function () { - runs(function () { - expect(state.videoCaption.frozen).not.toBeFalsy(); - expect(state.videoCaption.onMouseLeave).toHaveBeenCalled(); - }); + expect(state.videoCaption.frozen).not.toBeFalsy(); + expect(state.videoCaption.onMouseLeave).toHaveBeenCalled(); }); describe('when the cursor is moving', function () { it('reset the freezing timeout', function () { - runs(function () { - $('.subtitles-menu').trigger(jQuery.Event('mousemove')); - expect(window.clearTimeout).toHaveBeenCalled(); - }); + $('.subtitles-menu').trigger(jQuery.Event('mousemove')); + expect(window.clearTimeout).toHaveBeenCalled(); }); }); describe('when the mouse is scrolling', function () { it('reset the freezing timeout', function () { - runs(function () { - $('.subtitles-menu').trigger(jQuery.Event('mousewheel')); - expect(window.clearTimeout).toHaveBeenCalled(); - }); + $('.subtitles-menu').trigger(jQuery.Event('mousewheel')); + expect(window.clearTimeout).toHaveBeenCalled(); }); }); }); @@ -533,7 +500,7 @@ beforeEach(function () { state.videoCaption.frozen = 100; - $.fn.scrollTo.reset(); + $.fn.scrollTo.calls.reset(); }); describe('always', function () { @@ -582,12 +549,12 @@ beforeEach(function () { state = jasmine.initializePlayer(); Caption = state.videoCaption; - spyOn($, 'ajaxWithPrefix').andCallThrough(); + spyOn($, 'ajaxWithPrefix').and.callThrough(); spyOn(Caption, 'renderCaption'); spyOn(Caption, 'bindHandlers'); spyOn(Caption, 'updatePlayTime'); spyOn(Caption, 'hideCaptions'); - spyOn(state, 'youtubeId').andReturn('Z5KLxerq05Y'); + spyOn(state, 'youtubeId').and.returnValue('Z5KLxerq05Y'); }); it('show transcript on language change', function () { @@ -609,7 +576,7 @@ expect(Caption.hideCaptions).toHaveBeenCalledWith(false, false); Caption.loaded = false; - Caption.hideCaptions.reset(); + Caption.hideCaptions.calls.reset(); state.hide_captions = true; Caption.fetchCaption(); @@ -683,7 +650,7 @@ msg = 'on error: transcripts are hidden if there are no transcripts'; it(msg, function () { spyOn(Caption, 'fetchAvailableTranslations'); - $.ajax.andCallFake(function (settings) { + $.ajax.and.callFake(function (settings) { _.result(settings, 'error'); }); @@ -693,7 +660,7 @@ expect($.ajaxWithPrefix).toHaveBeenCalled(); expect(Caption.fetchAvailableTranslations).not.toHaveBeenCalled(); - expect(Caption.hideCaptions.mostRecentCall.args) + expect(Caption.hideCaptions.calls.mostRecent().args) .toEqual([true, false]); }); @@ -701,8 +668,8 @@ 'with youtubeId if there are no additional transcripts'; it(msg, function () { spyOn(Caption, 'fetchAvailableTranslations'); - spyOn(Caption, 'fetchCaption').andCallThrough(); - $.ajax.andCallFake(function (settings) { + spyOn(Caption, 'fetchCaption').and.callThrough(); + $.ajax.and.callFake(function (settings) { _.result(settings, 'error'); }); @@ -712,19 +679,19 @@ Caption.fetchCaption(); expect(Caption.fetchAvailableTranslations).not.toHaveBeenCalled(); - expect($.ajaxWithPrefix.mostRecentCall.args[0]['data']) + expect($.ajaxWithPrefix.calls.mostRecent().args[0].data) .toEqual({'videoId':'Z5KLxerq05Y'}); - expect(Caption.hideCaptions.mostRecentCall.args) + expect(Caption.hideCaptions.calls.mostRecent().args) .toEqual([true, false]); - expect(Caption.fetchCaption.mostRecentCall.args[0]).toEqual(true); - expect(Caption.fetchCaption.callCount).toEqual(2); + expect(Caption.fetchCaption.calls.mostRecent().args[0]).toEqual(true); + expect(Caption.fetchCaption.calls.count()).toEqual(2); }); msg = 'on success: when fetchCaption called with fetch_with_youtubeId to ' + 'get transcript with youtubeId for html5'; it(msg, function () { spyOn(Caption, 'fetchAvailableTranslations'); - spyOn(Caption, 'fetchCaption').andCallThrough(); + spyOn(Caption, 'fetchCaption').and.callThrough(); Caption.loaded = true; state.config.transcriptLanguages = {}; @@ -733,18 +700,18 @@ Caption.fetchCaption(true); expect(Caption.fetchAvailableTranslations).not.toHaveBeenCalled(); - expect($.ajaxWithPrefix.mostRecentCall.args[0]['data']) + expect($.ajaxWithPrefix.calls.mostRecent().args[0].data) .toEqual({'videoId':'Z5KLxerq05Y'}); expect(Caption.hideCaptions).toHaveBeenCalledWith(false); - expect(Caption.fetchCaption.mostRecentCall.args[0]).toEqual(true); - expect(Caption.fetchCaption.callCount).toEqual(1); + expect(Caption.fetchCaption.calls.mostRecent().args[0]).toEqual(true); + expect(Caption.fetchCaption.calls.count()).toEqual(1); }); msg = 'on error: fetch available translations if there are ' + 'additional transcripts'; it(msg, function () { $.ajax - .andCallFake(function (settings) { + .and.callFake(function (settings) { _.result(settings, 'error'); }); @@ -767,7 +734,7 @@ beforeEach(function () { state = jasmine.initializePlayer(); Caption = state.videoCaption; - spyOn($, 'ajaxWithPrefix').andCallThrough(); + spyOn($, 'ajaxWithPrefix').and.callThrough(); spyOn(Caption, 'hideCaptions'); spyOn(Caption, 'fetchCaption'); spyOn(Caption, 'renderLanguageMenu'); @@ -821,7 +788,7 @@ msg = 'on error: transcripts are hidden if there are no transcript'; it(msg, function () { - $.ajax.andCallFake(function (settings) { + $.ajax.and.callFake(function (settings) { _.result(settings, 'error'); }); Caption.fetchAvailableTranslations(); @@ -834,55 +801,44 @@ describe('play', function () { describe('when the transcript was not rendered', function () { - beforeEach(function () { - window.onTouchBasedDevice.andReturn(['iPad']); + beforeEach(function (done) { + window.onTouchBasedDevice.and.returnValue(['iPad']); - runs(function () { - state = jasmine.initializePlayer(); - state.videoCaption.play(); - }); + state = jasmine.initializePlayer(); + state.videoCaption.play(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); + }).then(function(){ + done(); + }); }); it('render the transcript', function () { - runs(function () { - var captionsData; + var captionsData; - captionsData = jasmine.stubbedCaption; - $('.subtitles li[data-index]').each( - function (index, link) { + captionsData = jasmine.stubbedCaption; - expect($(link)).toHaveData('index', index); - expect($(link)).toHaveData( - 'start', captionsData.start[index] - ); - expect($(link)).toHaveAttr('tabindex', 0); - expect($(link)).toHaveText(captionsData.text[index]); - }); + $('.subtitles li[data-index]').each( + function (index, item) { + expect(parseIntAttribute($(item), 'data-index')).toEqual(index); + expect(parseIntAttribute($(item), 'data-start')).toEqual(captionsData.start[index]); + expect($(item).attr('tabindex')).toEqual(0); + expect($(item).text().trim()).toEqual(captionsData.text[index]); }); - }); it('add a padding element to transcript', function () { - runs(function () { - expect($('.subtitles li:first')).toBe('.spacing'); - expect($('.subtitles li:last')).toBe('.spacing'); - }); + expect($('.subtitles li:first')).toHaveClass('spacing'); + expect($('.subtitles li:last')).toHaveClass('spacing'); }); it('set rendered to true', function () { - runs(function () { - expect(state.videoCaption.rendered).toBeTruthy(); - }); + expect(state.videoCaption.rendered).toBeTruthy(); }); it('set playing to true', function () { - runs(function () { - expect(state.videoCaption.playing).toBeTruthy(); - }); + expect(state.videoCaption.playing).toBeTruthy(); }); }); }); @@ -900,178 +856,148 @@ }); describe('updatePlayTime', function () { - beforeEach(function () { - runs(function () { - state = jasmine.initializePlayer(); - }); + beforeEach(function (done) { + state = jasmine.initializePlayer(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); + }).then(done); }); describe('when the video speed is 1.0x', function () { it('search the caption based on time', function () { - runs(function () { - state.videoCaption.updatePlayTime(25.000); - expect(state.videoCaption.currentIndex).toEqual(5); + state.videoCaption.updatePlayTime(25.000); + expect(state.videoCaption.currentIndex).toEqual(5); - // Flash mode - spyOn(state, 'isFlashMode').andReturn(true); - state.speed = '1.0'; - state.videoCaption.updatePlayTime(25.000); - expect(state.videoCaption.currentIndex).toEqual(5); - }); + // Flash mode + spyOn(state, 'isFlashMode').and.returnValue(true); + state.speed = '1.0'; + state.videoCaption.updatePlayTime(25.000); + expect(state.videoCaption.currentIndex).toEqual(5); }); }); describe('when the video speed is not 1.0x', function () { it('search the transcript based on 1.0x speed', function () { - runs(function () { - state.videoCaption.updatePlayTime(25.000); - expect(state.videoCaption.currentIndex).toEqual(5); + state.videoCaption.updatePlayTime(25.000); + expect(state.videoCaption.currentIndex).toEqual(5); - // To test speed, don't use start / end times. - state.config.startTime = 0; - state.config.endTime = null; + // To test speed, don't use start / end times. + state.config.startTime = 0; + state.config.endTime = null; - // Flash mode - state.speed = '2.0'; - spyOn(state, 'isFlashMode').andReturn(true); - state.videoCaption.updatePlayTime(25.000); - expect(state.videoCaption.currentIndex).toEqual(9); - state.speed = '0.75'; - state.videoCaption.updatePlayTime(25.000); - expect(state.videoCaption.currentIndex).toEqual(3); - }); + // Flash mode + state.speed = '2.0'; + spyOn(state, 'isFlashMode').and.returnValue(true); + state.videoCaption.updatePlayTime(25.000); + expect(state.videoCaption.currentIndex).toEqual(9); + state.speed = '0.75'; + state.videoCaption.updatePlayTime(25.000); + expect(state.videoCaption.currentIndex).toEqual(3); }); }); describe('when the index is not the same', function () { beforeEach(function () { - runs(function () { - state.videoCaption.currentIndex = 1; - $('.subtitles li[data-index=5]').addClass('current'); - state.videoCaption.updatePlayTime(25.000); - }); + state.videoCaption.currentIndex = 1; + $('.subtitles li[data-index=5]').addClass('current'); + state.videoCaption.updatePlayTime(25.000); }); it('deactivate the previous transcript', function () { - runs(function () { - expect($('.subtitles li[data-index=1]')) - .not.toHaveClass('current'); - }); + expect($('.subtitles li[data-index=1]')) + .not.toHaveClass('current'); }); it('activate new transcript', function () { - runs(function () { - expect($('.subtitles li[data-index=5]')) - .toHaveClass('current'); - }); + expect($('.subtitles li[data-index=5]')) + .toHaveClass('current'); }); it('save new index', function () { - runs(function () { - expect(state.videoCaption.currentIndex).toEqual(5); - }); + expect(state.videoCaption.currentIndex).toEqual(5); }); it('scroll transcript to new position', function () { - runs(function () { - expect($.fn.scrollTo).toHaveBeenCalled(); - }); + expect($.fn.scrollTo).toHaveBeenCalled(); }); }); describe('when the index is the same', function () { it('does not change current subtitle', function () { - runs(function () { - state.videoCaption.currentIndex = 1; - $('.subtitles li[data-index=3]').addClass('current'); - state.videoCaption.updatePlayTime(15.000); - expect($('.subtitles li[data-index=3]')) - .toHaveClass('current'); - }); + state.videoCaption.currentIndex = 1; + $('.subtitles li[data-index=3]').addClass('current'); + state.videoCaption.updatePlayTime(15.000); + expect($('.subtitles li[data-index=3]')) + .toHaveClass('current'); }); }); }); describe('resize', function () { - beforeEach(function () { - runs(function () { - state = jasmine.initializePlayer(); - }); + beforeEach(function (done) { + state = jasmine.initializePlayer(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { videoControl = state.videoControl; $('.subtitles li[data-index=1]').addClass('current'); state.videoCaption.onResize(); - }); + }).always(done); }); describe('set the height of transcript container', function () { it('when transcript button is enabled', function () { - runs(function () { - var realHeight = parseInt( - $('.subtitles').css('maxHeight'), 10 - ), - shouldBeHeight = $('.video-wrapper').height(); + var realHeight = parseInt( + $('.subtitles').css('maxHeight'), 10 + ), + shouldBeHeight = $('.video-wrapper').height(); - // Because of some problems with rounding on different - // environments: Linux * Mac * FF * Chrome - expect(realHeight).toBeCloseTo(shouldBeHeight, 2); - }); + // Because of some problems with rounding on different + // environments: Linux * Mac * FF * Chrome + expect(realHeight).toBeCloseTo(shouldBeHeight, 2); }); it('when transcript button is disabled ', function () { - runs(function () { - var realHeight, videoWrapperHeight, progressSliderHeight, - controlHeight, shouldBeHeight; + var realHeight, videoWrapperHeight, progressSliderHeight, + controlHeight, shouldBeHeight; - state.captionsHidden = true; - state.videoCaption.setSubtitlesHeight(); + state.captionsHidden = true; + state.videoCaption.setSubtitlesHeight(); - realHeight = parseInt( - $('.subtitles').css('maxHeight'), 10 - ); - videoWrapperHeight = $('.video-wrapper').height(); - progressSliderHeight = state.el.find('.slider').height(); - controlHeight = state.el.find('.video-controls').height(); - shouldBeHeight = videoWrapperHeight - - 0.5 * progressSliderHeight - - controlHeight; + realHeight = parseInt( + $('.subtitles').css('maxHeight'), 10 + ); + videoWrapperHeight = $('.video-wrapper').height(); + progressSliderHeight = state.el.find('.slider').height(); + controlHeight = state.el.find('.video-controls').height(); + shouldBeHeight = videoWrapperHeight - + 0.5 * progressSliderHeight - + controlHeight; - expect(realHeight).toBe(shouldBeHeight); - }); + expect(realHeight).toBe(shouldBeHeight); }); }); it('set the height of transcript spacing', function () { - runs(function () { - var firstSpacing, lastSpacing; + var firstSpacing, lastSpacing; - firstSpacing = Math.abs(parseInt( - $('.subtitles .spacing:first').css('height'), 10 - )); - lastSpacing = Math.abs(parseInt( - $('.subtitles .spacing:last').css('height'), 10 - )); + firstSpacing = Math.abs(parseInt( + $('.subtitles .spacing:first').css('height'), 10 + )); + lastSpacing = Math.abs(parseInt( + $('.subtitles .spacing:last').css('height'), 10 + )); - expect(firstSpacing - state.videoCaption.topSpacingHeight()) - .toBeLessThan(1); - expect(lastSpacing - state.videoCaption.bottomSpacingHeight()) - .toBeLessThan(1); - }); + expect(firstSpacing - state.videoCaption.topSpacingHeight()) + .toBeLessThan(1); + expect(lastSpacing - state.videoCaption.bottomSpacingHeight()) + .toBeLessThan(1); }); it('scroll transcript to new position', function () { - runs(function () { - expect($.fn.scrollTo).toHaveBeenCalled(); - }); + expect($.fn.scrollTo).toHaveBeenCalled(); }); }); @@ -1193,7 +1119,11 @@ beforeEach(function () { state.el.addClass('closed'); state.videoCaption.toggle(jQuery.Event('click')); - jasmine.Clock.useMock(); + jasmine.clock().install(); + }); + + afterEach(function () { + jasmine.clock().uninstall(); }); it('show the transcript', function () { @@ -1204,7 +1134,7 @@ xit('scroll the transcript', function () { // After transcripts are shown, and the video plays for a // bit. - jasmine.Clock.tick(1000); + jasmine.clock().tick(1000); // The transcripts should have advanced by at least one // position. When they advance, the list scrolls. The @@ -1218,60 +1148,46 @@ }); describe('transcript accessibility', function () { - beforeEach(function () { - runs(function () { - state = jasmine.initializePlayer(); - }); + beforeEach(function (done) { + state = jasmine.initializePlayer(); - waitsFor(function () { + jasmine.waitUntil(function () { return state.videoCaption.rendered; - }, 'Transcripts are not rendered', WAIT_TIMEOUT); + }).then(done); }); describe('when getting focus through TAB key', function () { beforeEach(function () { - runs(function () { - state.videoCaption.isMouseFocus = false; - $('.subtitles li[data-index=0]').trigger( - jQuery.Event('focus') - ); - }); + state.videoCaption.isMouseFocus = false; + $('.subtitles li[data-index=0]').trigger( + jQuery.Event('focus') + ); }); it('shows an outline around the transcript', function () { - runs(function () { - expect($('.subtitles li[data-index=0]')) - .toHaveClass('focused'); - }); + expect($('.subtitles li[data-index=0]')) + .toHaveClass('focused'); }); it('has automatic scrolling disabled', function () { - runs(function () { - expect(state.videoCaption.autoScrolling).toBe(false); - }); + expect(state.videoCaption.autoScrolling).toBe(false); }); }); describe('when loosing focus through TAB key', function () { beforeEach(function () { - runs(function () { - $('.subtitles li[data-index=0]').trigger( - jQuery.Event('blur') - ); - }); + $('.subtitles li[data-index=0]').trigger( + jQuery.Event('blur') + ); }); it('does not show an outline around the transcript', function () { - runs(function () { - expect($('.subtitles li[data-index=0]')) - .not.toHaveClass('focused'); - }); + expect($('.subtitles li[data-index=0]')) + .not.toHaveClass('focused'); }); it('has automatic scrolling enabled', function () { - runs(function () { - expect(state.videoCaption.autoScrolling).toBe(true); - }); + expect(state.videoCaption.autoScrolling).toBe(true); }); }); @@ -1281,26 +1197,20 @@ function () { beforeEach(function () { - runs(function () { - state.videoCaption.isMouseFocus = false; - $('.subtitles li[data-index=0]') - .trigger(jQuery.Event('focus')); - $('.subtitles li[data-index=0]') - .trigger(jQuery.Event('mousedown')); - }); + state.videoCaption.isMouseFocus = false; + $('.subtitles li[data-index=0]') + .trigger(jQuery.Event('focus')); + $('.subtitles li[data-index=0]') + .trigger(jQuery.Event('mousedown')); }); it('does not show an outline around it', function () { - runs(function () { - expect($('.subtitles li[data-index=0]')) - .not.toHaveClass('focused'); - }); + expect($('.subtitles li[data-index=0]')) + .not.toHaveClass('focused'); }); it('has automatic scrolling enabled', function () { - runs(function () { - expect(state.videoCaption.autoScrolling).toBe(true); - }); + expect(state.videoCaption.autoScrolling).toBe(true); }); }); @@ -1312,37 +1222,29 @@ var subDataLiIdx__0, subDataLiIdx__1; beforeEach(function () { - runs(function () { - subDataLiIdx__0 = $('.subtitles li[data-index=0]'); - subDataLiIdx__1 = $('.subtitles li[data-index=1]'); + subDataLiIdx__0 = $('.subtitles li[data-index=0]'); + subDataLiIdx__1 = $('.subtitles li[data-index=1]'); - state.videoCaption.isMouseFocus = false; + state.videoCaption.isMouseFocus = false; - subDataLiIdx__0.trigger(jQuery.Event('focus')); - subDataLiIdx__0.trigger(jQuery.Event('blur')); + subDataLiIdx__0.trigger(jQuery.Event('focus')); + subDataLiIdx__0.trigger(jQuery.Event('blur')); - state.videoCaption.isMouseFocus = true; + state.videoCaption.isMouseFocus = true; - subDataLiIdx__1.trigger(jQuery.Event('mousedown')); - }); + subDataLiIdx__1.trigger(jQuery.Event('mousedown')); }); it('does not show an outline around the first', function () { - runs(function () { - expect(subDataLiIdx__0).not.toHaveClass('focused'); - }); + expect(subDataLiIdx__0).not.toHaveClass('focused'); }); it('does not show an outline around the second', function () { - runs(function () { - expect(subDataLiIdx__1).not.toHaveClass('focused'); - }); + expect(subDataLiIdx__1).not.toHaveClass('focused'); }); it('has automatic scrolling enabled', function () { - runs(function () { - expect(state.videoCaption.autoScrolling).toBe(true); - }); + expect(state.videoCaption.autoScrolling).toBe(true); }); }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_context_menu_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_context_menu_spec.js index 96b854340b..ef4b20bccb 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_context_menu_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_context_menu_spec.js @@ -6,7 +6,6 @@ openMenu = function () { var container = $('.video'); - jasmine.Clock.useMock(); container.find('video').trigger('contextmenu'); menu = container.children('.contextmenu'); menuItems = menu.children('.menu-item').not('.submenu-item'); @@ -23,19 +22,19 @@ openSubmenuMouse = function (menuSubmenuItem) { menuSubmenuItem.mouseover(); - jasmine.Clock.tick(200); + jasmine.clock().tick(200); expect(menuSubmenuItem).toHaveClass('is-opened'); }; openSubmenuKeyboard = function (menuSubmenuItem, keyCode) { menuSubmenuItem.focus().trigger(keyPressEvent(keyCode || $.ui.keyCode.RIGHT)); expect(menuSubmenuItem).toHaveClass('is-opened'); - expect(menuSubmenuItem.children().first()).toBeFocused(); + expect(menuSubmenuItem.children().last().children().first()).toBeFocused(); }; closeSubmenuMouse = function (menuSubmenuItem) { menuSubmenuItem.mouseleave(); - jasmine.Clock.tick(200); + jasmine.clock().tick(200); expect(menuSubmenuItem).not.toHaveClass('is-opened'); }; @@ -46,20 +45,20 @@ }; beforeEach(function () { + jasmine.clock().install(); // $.cookie is mocked, make sure we have a state with an unmuted volume. - $.cookie.andReturn('100'); - this.addMatchers({ - toBeFocused: function () { + $.cookie.and.returnValue('100'); + jasmine.addMatchers({ + toHaveCorrectLabels: function () { return { - compare: function (actual) { - return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement }; + compare: function (actual, labelsList) { + return { + pass: _.difference(labelsList, _.map(actual, function (item) { + return $(item).text(); + })).length === 0 + }; } }; - }, - toHaveCorrectLabels: function (labelsList) { - return _.difference(labelsList, _.map(this.actual, function (item) { - return $(item).text(); - })).length === 0; } }); }); @@ -69,6 +68,7 @@ _.result(state.storage, 'clear'); _.result($('video').data('contextmenu'), 'destroy'); _.result(state.videoPlayer, 'destroy'); + jasmine.clock().uninstall(); }); describe('constructor', function () { @@ -89,7 +89,7 @@ */ // Only one context menu per video container - expect(menu).toExist(); + expect(menu).toBeInDOM(); expect(menu).toHaveClass('is-opened'); expect(menuItems).toHaveCorrectLabels(['Play', 'Mute', 'Fill browser']); expect(menuSubmenuItem.children('span')).toHaveText('Speed'); @@ -141,8 +141,8 @@ menuEvents = ['keydown', 'contextmenu', 'mouseleave', 'mouseover']; menu.data('menu').destroy(); - expect(menu).not.toExist(); - expect(overlay).not.toExist(); + expect(menu).not.toBeInDOM(); + expect(overlay).not.toBeInDOM(); _.each(menuitemEvents, function (eventName) { expect(menuItems.first()).not.toHandle(eventName); }) @@ -177,7 +177,7 @@ it('context menu opens', function () { expect(menu).toHaveClass('is-opened'); - expect(overlay).toExist(); + expect(overlay).toBeInDOM(); }); it('mouseover and mouseleave behave as expected', function () { @@ -193,25 +193,25 @@ // Left-click outside of open menu, for example on Play button playButton.click(); expect(menu).not.toHaveClass('is-opened'); - expect(overlay).not.toExist(); + expect(overlay).not.toBeInDOM(); }); it('mouse right-clicking outside of video will close it', function () { // Right-click outside of open menu for example on Play button playButton.trigger('contextmenu'); expect(menu).not.toHaveClass('is-opened'); - expect(overlay).not.toExist(); + expect(overlay).not.toBeInDOM(); }); it('mouse right-clicking inside video but outside of context menu will not close it', function () { - spyOn(menu.data('menu'), 'pointInContainerBox').andReturn(true); + spyOn(menu.data('menu'), 'pointInContainerBox').and.returnValue(true); overlay.trigger('contextmenu'); expect(menu).toHaveClass('is-opened'); - expect(overlay).toExist(); + expect(overlay).toBeInDOM(); }); it('mouse right-clicking inside video but outside of context menu will close submenus', function () { - spyOn(menu.data('menu'), 'pointInContainerBox').andReturn(true); + spyOn(menu.data('menu'), 'pointInContainerBox').and.returnValue(true); openSubmenuMouse(menuSubmenuItem); expect(menuSubmenuItem).toHaveClass('is-opened'); overlay.trigger('contextmenu'); @@ -221,12 +221,12 @@ it('mouse left/right-clicking behaves as expected on play/pause menu item', function () { var menuItem = menuItems.first(); spyOn(state.videoPlayer, 'isPlaying'); - spyOn(state.videoPlayer, 'play').andCallFake(function () { - state.videoPlayer.isPlaying.andReturn(true); + spyOn(state.videoPlayer, 'play').and.callFake(function () { + state.videoPlayer.isPlaying.and.returnValue(true); state.el.trigger('play'); }); - spyOn(state.videoPlayer, 'pause').andCallFake(function () { - state.videoPlayer.isPlaying.andReturn(false); + spyOn(state.videoPlayer, 'pause').and.callFake(function () { + state.videoPlayer.isPlaying.and.returnValue(false); state.el.trigger('pause'); }); // Left-click on play @@ -238,7 +238,7 @@ menuItem.click(); expect(state.videoPlayer.pause).toHaveBeenCalled(); expect(menuItem).toHaveText('Play'); - state.videoPlayer.play.reset(); + state.videoPlayer.play.calls.reset(); // Right-click on play menuItem.trigger('contextmenu'); expect(state.videoPlayer.play).toHaveBeenCalled(); @@ -355,14 +355,14 @@ it('close the menu on ESCAPE keydown', function () { menu.trigger(keyPressEvent($.ui.keyCode.ESCAPE)); expect(menu).not.toHaveClass('is-opened'); - expect(overlay).not.toExist(); + expect(overlay).not.toBeInDOM(); }); it('close the submenu on ESCAPE keydown', function () { openSubmenuKeyboard(menuSubmenuItem); menuSubmenuItem.trigger(keyPressEvent($.ui.keyCode.ESCAPE)); expect(menuSubmenuItem).not.toHaveClass('is-opened'); - expect(overlay).not.toExist(); + expect(overlay).not.toBeInDOM(); }); it('close the submenu on LEFT keydown on submenu items', function () { @@ -395,9 +395,9 @@ menuItems.eq(0).trigger(keyPressEvent($.ui.keyCode.UP)); expect(menuSubmenuItem).toBeFocused(); // Speed - menuSubmenuItem.trigger(keyPressEvent($.ui.keyCode.UP)); // Check if hidden item can be skipped correctly. menuItems.eq(2).hide(); // hide Fullscreen item + menuSubmenuItem.trigger(keyPressEvent($.ui.keyCode.UP)); expect(menuItems.eq(1)).toBeFocused(); // Mute menuItems.eq(1).trigger(keyPressEvent($.ui.keyCode.UP)); expect(menuItems.eq(0)).toBeFocused(); // Play diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_control_spec.js index 85794dc2d5..eb47c399ab 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_control_spec.js @@ -7,7 +7,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); }); afterEach(function () { @@ -24,7 +24,7 @@ }); it('render the video controls', function () { - expect($('.video-controls')).toContain( + expect($('.video-controls')).toContainElement( [ '.slider', 'ul.vcr', @@ -41,61 +41,52 @@ describe('constructor with start-time', function () { it( 'saved position is 0, timer slider and VCR set to start-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - savedVideoPosition: 0 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + savedVideoPosition: 0 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); - - return isFinite(duration) && duration > 0 && - isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 1:00'); expectedValue = sliderEl.slider('option', 'value'); expect(expectedValue).toBe(10); - }); + }).always(done); }); it( 'saved position is after start-time, ' + 'timer slider and VCR set to saved position', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - savedVideoPosition: 15 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + savedVideoPosition: 15 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:15 / 1:00'); @@ -103,34 +94,30 @@ expect(expectedValue).toBe(15); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is negative, ' + 'timer slider and VCR set to start-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - savedVideoPosition: -15 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + savedVideoPosition: -15 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 1:00'); @@ -138,34 +125,30 @@ expect(expectedValue).toBe(10); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is not a number, ' + 'timer slider and VCR set to start-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - savedVideoPosition: 'a' - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + savedVideoPosition: 'a' }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 1:00'); @@ -173,34 +156,30 @@ expect(expectedValue).toBe(10); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is greater than end-time, ' + 'timer slider and VCR set to start-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - savedVideoPosition: 10000 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + savedVideoPosition: 10000 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 1:00'); @@ -208,7 +187,7 @@ expect(expectedValue).toBe(10); state.storage.clear(); - }); + }).always(done); }); }); @@ -216,28 +195,24 @@ it( 'saved position is 0, timer slider and VCR set to 0:00 ' + 'and ending at specified end-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - end: 20, - savedVideoPosition: 0 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + end: 20, + savedVideoPosition: 0 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:00 / 0:20'); @@ -245,34 +220,30 @@ expect(expectedValue).toBe(0); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is after start-time, ' + 'timer slider and VCR set to saved position', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - end: 20, - savedVideoPosition: 15 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + end: 20, + savedVideoPosition: 15 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:15 / 0:20'); @@ -280,34 +251,30 @@ expect(expectedValue).toBe(15); state.storage.clear(); - }); + }).always(done); }); // TODO: Fix! it( 'saved position is negative, timer slider and VCR set to 0:00', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - end: 20, - savedVideoPosition: -15 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + end: 20, + savedVideoPosition: -15 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:00 / 0:20'); @@ -315,34 +282,30 @@ expect(expectedValue).toBe(0); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is not a number, ' + 'timer slider and VCR set to 0:00', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - end: 20, - savedVideoPosition: 'a' - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + end: 20, + savedVideoPosition: 'a' }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:00 / 0:20'); @@ -350,35 +313,31 @@ expect(expectedValue).toBe(0); state.storage.clear(); - }); + }).always(done); }); // TODO: Fix! it( 'saved position is greater than end-time, ' + 'timer slider and VCR set to 0:00', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - end: 20, - savedVideoPosition: 10000 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + end: 20, + savedVideoPosition: 10000 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:00 / 0:20'); @@ -386,36 +345,32 @@ expect(expectedValue).toBe(0); state.storage.clear(); - }); + }).always(done); }); }); describe('constructor with start-time and end-time', function () { it( 'saved position is 0, timer slider and VCR set to appropriate start and end times', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - end: 20, - savedVideoPosition: 0 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + end: 20, + savedVideoPosition: 0 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 0:20'); @@ -423,35 +378,31 @@ expect(expectedValue).toBe(10); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is after start-time, ' + 'timer slider and VCR set to saved position', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - end: 20, - savedVideoPosition: 15 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + end: 20, + savedVideoPosition: 15 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:15 / 0:20'); @@ -459,35 +410,31 @@ expect(expectedValue).toBe(15); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is negative, ' + 'timer slider and VCR set to start-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - end: 20, - savedVideoPosition: -15 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + end: 20, + savedVideoPosition: -15 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 0:20'); @@ -495,35 +442,31 @@ expect(expectedValue).toBe(10); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is not a number, ' + 'timer slider and VCR set to start-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - end: 20, - savedVideoPosition: 'a' - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + end: 20, + savedVideoPosition: 'a' }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 0:20'); @@ -531,35 +474,31 @@ expect(expectedValue).toBe(10); state.storage.clear(); - }); + }).always(done); }); it( 'saved position is greater than end-time, ' + 'timer slider and VCR set to start-time', - function () + function (done) { var duration, sliderEl, expectedValue; - runs(function () { - window.VideoState = {}; - state = jasmine.initializePlayer({ - start: 10, - end: 20, - savedVideoPosition: 10000 - }); - sliderEl = state.videoProgressSlider.slider; - spyOn(state.videoPlayer, 'duration').andReturn(60); + window.VideoState = {}; + state = jasmine.initializePlayer({ + start: 10, + end: 20, + savedVideoPosition: 10000 }); + sliderEl = state.videoProgressSlider.slider; + spyOn(state.videoPlayer, 'duration').and.returnValue(60); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return isFinite(duration) && duration > 0 && isFinite(state.videoPlayer.startTime); - }, 'duration is set', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expectedValue = $('.video-controls').find('.vidtime'); expect(expectedValue).toHaveText('0:10 / 0:20'); @@ -567,7 +506,7 @@ expect(expectedValue).toBe(10); state.storage.clear(); - }); + }).always(done); }); }); @@ -587,16 +526,15 @@ expect(state.videoControl).toBeUndefined(); }); - it('can focus the first control', function () { + it('can focus the first control', function (done) { var btnPlay; state = jasmine.initializePlayer({focusFirstControl: true}); btnPlay = state.el.find('.video-controls .play'); - waitsFor(function () { + jasmine.waitUntil(function () { return state.el.hasClass('is-initialized'); - }, 'Player is not initialized', WAIT_TIMEOUT); - runs(function () { + }).then(function () { expect(btnPlay).toBeFocused(); - }); + }).always(done); }); }); }).call(this, window.WAIT_TIMEOUT); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_events_bumper_plugin_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_events_bumper_plugin_spec.js index e41b40e782..4a0f1177e2 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_events_bumper_plugin_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_events_bumper_plugin_spec.js @@ -1,20 +1,20 @@ (function (undefined) { 'use strict'; describe('VideoPlayer Events Bumper plugin', function () { + var Logger = window.Logger; var state, oldOTBD; beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine .createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); - jasmine.stubRequests(); state = jasmine.initializePlayer('video_with_bumper.html'); spyOn(Logger, 'log'); $('.poster .btn-play').click(); - spyOn(state.bumperState.videoEventsBumperPlugin, 'getCurrentTime').andReturn(10); - spyOn(state.bumperState.videoEventsBumperPlugin, 'getDuration').andReturn(20); + spyOn(state.bumperState.videoEventsBumperPlugin, 'getCurrentTime').and.returnValue(10); + spyOn(state.bumperState.videoEventsBumperPlugin, 'getDuration').and.returnValue(20); }); afterEach(function () { @@ -33,7 +33,7 @@ state.el.trigger('ready'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.loaded', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', duration: 20 }); @@ -43,7 +43,7 @@ state.el.trigger('play'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.played', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', currentTime: 10, duration: 20 @@ -54,17 +54,17 @@ state.el.trigger('ended'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.stopped', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', currentTime: 10, duration: 20 }); - Logger.log.reset(); + Logger.log.calls.reset(); state.el.trigger('stop'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.stopped', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', currentTime: 10, duration: 20 @@ -75,7 +75,7 @@ state.el.trigger('skip', [false]); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.skipped', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', currentTime: 10, duration: 20 @@ -86,7 +86,7 @@ state.el.trigger('skip', [true]); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.dismissed', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', currentTime: 10, duration: 20 @@ -97,7 +97,7 @@ state.el.trigger('language_menu:show'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.transcript.menu.shown', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', duration: 20 }); @@ -107,7 +107,7 @@ state.el.trigger('language_menu:hide'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.transcript.menu.hidden', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', duration: 20 }); @@ -117,7 +117,7 @@ state.el.trigger('captions:show'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.transcript.shown', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', currentTime: 10, duration: 20 @@ -128,7 +128,7 @@ state.el.trigger('captions:hide'); expect(Logger.log).toHaveBeenCalledWith('edx.video.bumper.transcript.hidden', { host_component_id: 'id', - bumper_id: 'xmodule/include/fixtures/test.mp4', + bumper_id: '/base/fixtures/test.mp4', code: 'html5', currentTime: 10, duration: 20 @@ -137,7 +137,7 @@ it('can destroy itself', function () { var plugin = state.bumperState.videoEventsBumperPlugin; - spyOn($.fn, 'off').andCallThrough(); + spyOn($.fn, 'off').and.callThrough(); plugin.destroy(); expect(state.bumperState.videoEventsBumperPlugin).toBeUndefined(); expect($.fn.off).toHaveBeenCalledWith({ diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_events_plugin_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_events_plugin_spec.js index b6896d19db..82f64b8c8d 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_events_plugin_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_events_plugin_spec.js @@ -7,12 +7,11 @@ oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine .createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); - jasmine.stubRequests(); state = jasmine.initializePlayer(); spyOn(Logger, 'log'); - spyOn(state.videoEventsPlugin, 'getCurrentTime').andReturn(10); + spyOn(state.videoEventsPlugin, 'getCurrentTime').and.returnValue(10); }); afterEach(function () { @@ -90,7 +89,7 @@ }); expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy(); - Logger.log.reset(); + Logger.log.calls.reset(); state.el.trigger('stop'); expect(Logger.log).toHaveBeenCalledWith('stop_video', { id: 'id', @@ -155,7 +154,7 @@ it('can destroy itself', function () { var plugin = state.videoEventsPlugin; - spyOn($.fn, 'off').andCallThrough(); + spyOn($.fn, 'off').and.callThrough(); state.videoEventsPlugin.destroy(); expect(state.videoEventsPlugin).toBeUndefined(); expect($.fn.off).toHaveBeenCalledWith({ diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_focus_grabber_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_focus_grabber_spec.js index 5f69d2c7c7..8dd9bceb40 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_focus_grabber_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_focus_grabber_spec.js @@ -15,17 +15,19 @@ // stack. jQuery.fx.off = true; + jasmine.stubRequests(); loadFixtures('video_html5.html'); state = new Video('#example'); spyOnEvent(state.el, 'mousemove'); - spyOn(state.focusGrabber, 'disableFocusGrabber').andCallThrough(); - spyOn(state.focusGrabber, 'enableFocusGrabber').andCallThrough(); + spyOn(state.focusGrabber, 'disableFocusGrabber').and.callThrough(); + spyOn(state.focusGrabber, 'enableFocusGrabber').and.callThrough(); }); afterEach(function () { // Turn jQuery animations back on. jQuery.fx.off = true; + state.storage.clear(); state.videoPlayer.destroy(); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_full_screen_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_full_screen_spec.js index 6aa858b73f..1bb36c82b4 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_full_screen_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_full_screen_spec.js @@ -6,7 +6,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); }); afterEach(function () { @@ -83,7 +83,7 @@ }); it('Controls height is actual on switch to fullscreen', function () { - spyOn($.fn, 'height').andCallFake(function (val) { + spyOn($.fn, 'height').and.callFake(function (val) { return _.isUndefined(val) ? 100: this; }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_play_pause_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_play_pause_control_spec.js index 0cbb23c1f1..dcb1fd4968 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_play_pause_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_play_pause_control_spec.js @@ -6,7 +6,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); state = jasmine.initializePlayer(); spyOn(state.videoCommands, 'execute'); spyOn(state.videoSaveStatePlugin, 'saveState'); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_play_placeholder_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_play_placeholder_spec.js index d99c12e24c..b7119dd9b4 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_play_placeholder_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_play_placeholder_spec.js @@ -6,7 +6,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(['iPad']); + .createSpy('onTouchBasedDevice').and.returnValue(['iPad']); state = jasmine.initializePlayer(); spyOn(state.videoCommands, 'execute'); @@ -41,7 +41,7 @@ beforeEach(function () { jasmine.stubRequests(); - spyOn(window.YT, 'Player').andCallThrough(); + spyOn(window.YT, 'Player').and.callThrough(); }); it ('works correctly on calling proper methods', function () { @@ -77,7 +77,7 @@ it(message, function () { var btnPlay; - window.onTouchBasedDevice.andReturn(data.isTouch); + window.onTouchBasedDevice.and.returnValue(data.isTouch); state = jasmine.initializePlayer(); btnPlay = state.el.find('.btn-play'); @@ -97,7 +97,7 @@ { var btnPlay; - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); state = jasmine.initializePlayer(); btnPlay = state.el.find('.btn-play'); @@ -113,7 +113,7 @@ { var btnPlay; - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); state = jasmine.initializePlayer(); btnPlay = state.el.find('.btn-play'); @@ -128,7 +128,7 @@ { var btnPlay; - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); state = jasmine.initializePlayerYouTube(); btnPlay = state.el.find('.btn-play'); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_play_skip_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_play_skip_control_spec.js index 7e15b597af..479de984ba 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_play_skip_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_play_skip_control_spec.js @@ -6,7 +6,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); state = jasmine.initializePlayer('video_with_bumper.html'); $('.poster .btn-play').click(); spyOn(state.bumperState.videoCommands, 'execute'); @@ -19,16 +19,19 @@ state.bumperState.videoPlayer.destroy(); } window.onTouchBasedDevice = oldOTBD; + if (state.videoPlayer) { + _.result(state.videoPlayer, 'destroy'); + } }); it('can render the control', function () { - expect($('.video_control.play')).toExist(); + expect($('.video_control.play')).toBeInDOM(); }); it('can update state on play', function () { state.el.trigger('play'); - expect($('.video_control.play')).not.toExist(); - expect($('.video_control.skip')).toExist(); + expect($('.video_control.play')).not.toBeInDOM(); + expect($('.video_control.skip')).toBeInDOM(); }); it('can start video playing on click', function () { @@ -38,7 +41,7 @@ it('can skip the video on click', function () { state.el.trigger('play'); - spyOn(state.bumperState.videoPlayer, 'isPlaying').andReturn(true); + spyOn(state.bumperState.videoPlayer, 'isPlaying').and.returnValue(true); $('.video_control.skip').first().click(); expect(state.bumperState.videoCommands.execute).toHaveBeenCalledWith('skip'); }); @@ -46,10 +49,10 @@ it('can destroy itself', function () { var plugin = state.bumperState.videoPlaySkipControl, el = plugin.el; - spyOn($.fn, 'off').andCallThrough(); + spyOn($.fn, 'off').and.callThrough(); plugin.destroy(); expect(state.bumperState.videoPlaySkipControl).toBeUndefined(); - expect(el).not.toExist(); + expect(el).not.toBeInDOM(); expect($.fn.off).toHaveBeenCalledWith('destroy', plugin.destroy); }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js index a8f8fd789b..f5f15ba133 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js @@ -5,12 +5,16 @@ require( ['video/03_video_player.js'], function (VideoPlayer) { describe('VideoPlayer', function () { - var state, oldOTBD; + var state, oldOTBD, empty_arguments; + + (function () { + empty_arguments = arguments; + })(); beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); }); afterEach(function () { @@ -73,7 +77,7 @@ function (VideoPlayer) { var events; jasmine.stubRequests(); - spyOn(window.YT, 'Player').andCallThrough(); + spyOn(window.YT, 'Player').and.callThrough(); state = jasmine.initializePlayerYouTube(); state.videoEl = $('video, iframe'); @@ -107,9 +111,9 @@ function (VideoPlayer) { state = jasmine.initializePlayerYouTube(); state.videoEl = state.el.find('video, iframe').width(100); player = state.videoPlayer.player; - player.getAvailablePlaybackRates.andReturn([1]); + player.getAvailablePlaybackRates.and.returnValue([1]); state.currentPlayerMode = 'html5'; - spyOn(window.YT, 'Player').andCallThrough(); + spyOn(window.YT, 'Player').and.callThrough(); state.videoPlayer.onReady(); expect(YT.Player).toHaveBeenCalledWith('id', { @@ -137,7 +141,7 @@ function (VideoPlayer) { describe('when on a touch based device', function () { $.each(['iPad', 'Android'], function (index, device) { it('create video volume control on' + device, function () { - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); @@ -167,7 +171,7 @@ function (VideoPlayer) { state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); - spyOn(state.videoPlayer, 'play').andCallThrough(); + spyOn(state.videoPlayer, 'play').and.callThrough(); state.videoPlayer.onReady(); }); @@ -204,7 +208,7 @@ function (VideoPlayer) { state = jasmine.initializePlayerYouTube(); state.videoEl = $('video, iframe'); - spyOn($.fn, 'trigger').andCallThrough(); + spyOn($.fn, 'trigger').and.callThrough(); state.videoPlayer.onStateChange({ data: YT.PlayerState.ENDED }); @@ -215,8 +219,8 @@ function (VideoPlayer) { }); it('trigger pause and ended events', function () { - expect($.fn.trigger).toHaveBeenCalledWith('pause', {}); - expect($.fn.trigger).toHaveBeenCalledWith('ended', {}); + expect($.fn.trigger).toHaveBeenCalledWith('pause', empty_arguments); + expect($.fn.trigger).toHaveBeenCalledWith('ended', empty_arguments); }); }); }); @@ -226,7 +230,7 @@ function (VideoPlayer) { beforeEach(function () { state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); - spyOn($.fn, 'trigger').andCallThrough(); + spyOn($.fn, 'trigger').and.callThrough(); state.videoPlayer.onStateChange({ data: YT.PlayerState.PAUSED @@ -238,7 +242,7 @@ function (VideoPlayer) { }); it('pause the video caption', function () { - expect($.fn.trigger).toHaveBeenCalledWith('pause', {}); + expect($.fn.trigger).toHaveBeenCalledWith('pause', empty_arguments); }); }); @@ -250,15 +254,15 @@ function (VideoPlayer) { state = jasmine.initializePlayer(); oldState = state; - spyOn(oldState.videoPlayer, 'onPause').andCallThrough(); + spyOn(oldState.videoPlayer, 'onPause').and.callThrough(); // Now initialize a second instance. state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); - spyOn(window, 'setInterval').andReturn(100); - spyOn($.fn, 'trigger').andCallThrough(); + spyOn(window, 'setInterval').and.returnValue(100); + spyOn($.fn, 'trigger').and.callThrough(); state.videoPlayer.onStateChange({ data: YT.PlayerState.PLAYING @@ -277,7 +281,7 @@ function (VideoPlayer) { }); it('play the video caption', function () { - expect($.fn.trigger).toHaveBeenCalledWith('play', {}); + expect($.fn.trigger).toHaveBeenCalledWith('play', empty_arguments); }); }); @@ -289,7 +293,7 @@ function (VideoPlayer) { state.videoEl = $('video, iframe'); - spyOn($.fn, 'trigger').andCallThrough(); + spyOn($.fn, 'trigger').and.callThrough(); state.videoPlayer.onStateChange({ data: YT.PlayerState.PLAYING }); @@ -310,7 +314,7 @@ function (VideoPlayer) { }); it('pause the video caption', function () { - expect($.fn.trigger).toHaveBeenCalledWith('pause', {}); + expect($.fn.trigger).toHaveBeenCalledWith('pause', empty_arguments); }); }); @@ -319,7 +323,7 @@ function (VideoPlayer) { state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); - spyOn($.fn, 'trigger').andCallThrough(); + spyOn($.fn, 'trigger').and.callThrough(); state.videoPlayer.onStateChange({ data: YT.PlayerState.ENDED }); @@ -330,7 +334,7 @@ function (VideoPlayer) { }); it('pause the video caption', function () { - expect($.fn.trigger).toHaveBeenCalledWith('ended', {}); + expect($.fn.trigger).toHaveBeenCalledWith('ended', empty_arguments); }); }); }); @@ -362,59 +366,51 @@ function (VideoPlayer) { describe('onSeek', function () { beforeEach(function () { // jasmine.Clock can't be used to fake out debounce with newer versions of underscore - spyOn(_, 'debounce').andCallFake(function (func) { + spyOn(_, 'debounce').and.callFake(function (func) { return function () { func.apply(this, arguments); }; }); state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); - spyOn(state.videoPlayer, 'duration').andReturn(120); + spyOn(state.videoPlayer, 'duration').and.returnValue(120); }); describe('when the video is playing', function () { - beforeEach(function () { - runs(function () { - state.videoPlayer.play(); - }); + beforeEach(function (done) { + state.videoPlayer.play(); - waitsFor(function () { + jasmine.waitUntil(function() { return state.videoPlayer.isPlaying(); - }, 'video didn\'t start playing', WAIT_TIMEOUT); + }).done(done); }); it('call runTimer in seekTo on player', function () { - runs(function () { - spyOn(state.videoPlayer, 'stopTimer'); - spyOn(state.videoPlayer, 'runTimer'); - state.videoPlayer.seekTo(10); - expect(state.videoPlayer.currentTime).toBe(10); - expect(state.videoPlayer.stopTimer).toHaveBeenCalled(); - expect(state.videoPlayer.runTimer).toHaveBeenCalled(); - }); + spyOn(state.videoPlayer, 'stopTimer').and.callThrough(); + spyOn(state.videoPlayer, 'runTimer').and.callThrough(); + state.videoPlayer.seekTo(10); + expect(state.videoPlayer.currentTime).toBe(10); + expect(state.videoPlayer.stopTimer).toHaveBeenCalled(); + expect(state.videoPlayer.runTimer).toHaveBeenCalled(); }); it('seek the player', function () { - runs(function () { - spyOn(state.videoPlayer.player, 'seekTo').andCallThrough(); - state.videoProgressSlider.onSlide( - jQuery.Event('slide'), { value: 30 } - ); - expect(state.videoPlayer.currentTime).toBe(30); - expect(state.videoPlayer.player.seekTo).toHaveBeenCalledWith(30, true); - }); + spyOn(state.videoPlayer.player, 'seekTo').and.callThrough(); + state.videoProgressSlider.onSlide( + jQuery.Event('slide'), { value: 30 } + ); + expect(state.videoPlayer.currentTime).toBe(30); + expect(state.videoPlayer.player.seekTo).toHaveBeenCalledWith(30, true); }); it('call updatePlayTime on player', function () { - runs(function () { - spyOn(state.videoPlayer, 'updatePlayTime').andCallThrough(); - state.videoProgressSlider.onSlide( - jQuery.Event('slide'), { value: 30 } - ); - expect(state.videoPlayer.currentTime).toBe(30); - expect(state.videoPlayer.updatePlayTime).toHaveBeenCalledWith(30, true); - }); + spyOn(state.videoPlayer, 'updatePlayTime').and.callThrough(); + state.videoProgressSlider.onSlide( + jQuery.Event('slide'), { value: 30 } + ); + expect(state.videoPlayer.currentTime).toBe(30); + expect(state.videoPlayer.updatePlayTime).toHaveBeenCalledWith(30, true); }); }); @@ -433,7 +429,7 @@ function (VideoPlayer) { describe('when the video is not playing', function () { beforeEach(function () { spyOn(state.videoPlayer, 'setPlaybackRate') - .andCallThrough(); + .and.callThrough(); }); it('video has a correct speed', function () { @@ -442,7 +438,7 @@ function (VideoPlayer) { expect(state.videoPlayer.setPlaybackRate) .toHaveBeenCalledWith('2.0', true); state.videoPlayer.onPlay(); - expect(state.videoPlayer.setPlaybackRate.calls.length) + expect(state.videoPlayer.setPlaybackRate.calls.count()) .toEqual(1); }); }); @@ -483,7 +479,7 @@ function (VideoPlayer) { state.videoEl = $('video, iframe'); - spyOn(state.videoPlayer, 'updatePlayTime').andCallThrough(); + spyOn(state.videoPlayer, 'updatePlayTime').and.callThrough(); }); describe( @@ -535,29 +531,26 @@ function (VideoPlayer) { state.videoEl = $('video, iframe'); - spyOn(state.videoPlayer, 'update').andCallThrough(); - spyOn(state.videoPlayer, 'pause').andCallThrough(); + spyOn(state.videoPlayer, 'update').and.callThrough(); + spyOn(state.videoPlayer, 'pause').and.callThrough(); spyOn(state.videoProgressSlider, 'notifyThroughHandleEnd') - .andCallThrough(); + .and.callThrough(); }); it( 'video is paused on first endTime, start & end time are reset', - function () + function (done) { var duration; - state.videoProgressSlider.notifyThroughHandleEnd.reset(); - state.videoPlayer.pause.reset(); + state.videoProgressSlider.notifyThroughHandleEnd.calls.reset(); + state.videoPlayer.pause.calls.reset(); state.videoPlayer.play(); - waitsFor(function () { + jasmine.waitUntil(function () { duration = Math.round(state.videoPlayer.currentTime); - - return state.videoPlayer.pause.calls.length === 1; - }, 'pause() has been called', WAIT_TIMEOUT); - - runs(function () { + return state.videoPlayer.pause.calls.count() === 1; + }).then(function () { expect(state.videoPlayer.startTime).toBe(0); expect(state.videoPlayer.endTime).toBe(null); @@ -565,7 +558,7 @@ function (VideoPlayer) { expect(state.videoProgressSlider.notifyThroughHandleEnd) .toHaveBeenCalledWith({end: true}); - }); + }).always(done); }); }); @@ -573,14 +566,14 @@ function (VideoPlayer) { beforeEach(function () { state = jasmine.initializePlayerYouTube(); state.videoEl = $('video, iframe'); - spyOn(state.videoCaption, 'updatePlayTime').andCallThrough(); - spyOn(state.videoProgressSlider, 'updatePlayTime').andCallThrough(); + spyOn(state.videoCaption, 'updatePlayTime').and.callThrough(); + spyOn(state.videoProgressSlider, 'updatePlayTime').and.callThrough(); }); - it('update the video playback time', function () { + it('update the video playback time', function (done) { var duration = 0; - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); if (duration > 0) { @@ -588,40 +581,34 @@ function (VideoPlayer) { } return false; - }, 'Video is fully loaded.', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { state.videoPlayer.goToStartTime = false; state.videoPlayer.updatePlayTime(60); expect($('.vidtime')).toHaveHtml('1:00 / 1:00'); - }); + }).always(done); }); - it('update the playback time on caption', function () { - waitsFor(function () { + it('update the playback time on caption', function (done) { + jasmine.waitUntil(function () { return state.videoPlayer.duration() > 0; - }, 'Video is fully loaded.', WAIT_TIMEOUT); - - runs(function () { + }, 1000).then(function () { state.videoPlayer.goToStartTime = false; state.videoPlayer.updatePlayTime(60); expect(state.videoCaption.updatePlayTime) .toHaveBeenCalledWith(60); - }); + }).always(done); }); - it('update the playback time on progress slider', function () { + it('update the playback time on progress slider', function (done) { var duration = 0; - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return duration > 0; - }, 'Video is fully loaded.', WAIT_TIMEOUT); - - runs(function () { + }, 1000).then(function () { state.videoPlayer.goToStartTime = false; state.videoPlayer.updatePlayTime(60); @@ -630,7 +617,7 @@ function (VideoPlayer) { time: 60, duration: duration }); - }); + }).always(done); }); }); @@ -652,15 +639,15 @@ function (VideoPlayer) { state.videoEl = $('video, iframe'); - spyOn(state.videoPlayer, 'updatePlayTime').andCallThrough(); - spyOn(state.videoPlayer.player, 'seekTo').andCallThrough(); + spyOn(state.videoPlayer, 'updatePlayTime').and.callThrough(); + spyOn(state.videoPlayer.player, 'seekTo').and.callThrough(); spyOn(state.videoProgressSlider, 'updateStartEndTimeRegion') - .andCallThrough(); + .and.callThrough(); }); it( 'when duration becomes available, updatePlayTime() is called', - function () + function (done) { var duration; @@ -669,14 +656,12 @@ function (VideoPlayer) { state.videoPlayer.play(); - waitsFor(function () { + jasmine.waitUntil(function () { duration = state.videoPlayer.duration(); return state.videoPlayer.isPlaying() && state.videoPlayer.initialSeekToStartTime === false; - }, 'duration becomes available', WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(state.videoPlayer.startTime).toBe(START_TIME); expect(state.videoPlayer.endTime).toBe(END_TIME); @@ -688,7 +673,7 @@ function (VideoPlayer) { expect(state.videoPlayer.seekToStartTimeOldSpeed) .toBe(state.speed); - }); + }).always(done); }); }); @@ -708,7 +693,7 @@ function (VideoPlayer) { seekTo: function () {} }, figureOutStartEndTime: jasmine.createSpy(), - figureOutStartingTime: jasmine.createSpy().andReturn(0) + figureOutStartingTime: jasmine.createSpy().and.returnValue(0) }, config: { savedVideoPosition: 0, @@ -723,7 +708,7 @@ function (VideoPlayer) { currentPlayerMode: 'html5', trigger: function () {}, browserIsFirefox: false, - isFlashMode: jasmine.createSpy().andReturn(false) + isFlashMode: jasmine.createSpy().and.returnValue(false) }; }); }); @@ -733,7 +718,7 @@ function (VideoPlayer) { beforeEach(function () { state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); - spyOn($.fn, 'trigger').andCallThrough(); + spyOn($.fn, 'trigger').and.callThrough(); $('.add-fullscreen').click(); }); @@ -752,7 +737,7 @@ function (VideoPlayer) { beforeEach(function () { state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); - spyOn($.fn, 'trigger').andCallThrough(); + spyOn($.fn, 'trigger').and.callThrough(); state.el.addClass('video-fullscreen'); state.videoFullScreen.fullScreenState = true; state.videoFullScreen.isFullScreen = true; @@ -779,7 +764,7 @@ function (VideoPlayer) { state.videoEl = $('video, iframe'); - spyOn(state.videoPlayer.player, 'getDuration').andCallThrough(); + spyOn(state.videoPlayer.player, 'getDuration').and.callThrough(); state.videoPlayer.duration(); }); @@ -801,11 +786,11 @@ function (VideoPlayer) { state.videoEl = $('video, iframe'); - spyOn(state, 'getDuration').andCallThrough(); + spyOn(state, 'getDuration').and.callThrough(); // When `state.videoPlayer.player.getDuration()` returns a `0`, // the fall-back function `state.getDuration()` will be called. - state.videoPlayer.player.getDuration.andReturn(0); + state.videoPlayer.player.getDuration.and.returnValue(0); }); it('getDuration is called as a fall-back', function () { @@ -821,7 +806,7 @@ function (VideoPlayer) { state.videoEl = $('video, iframe'); - spyOn(state.videoPlayer.player, 'getVolume').andCallThrough(); + spyOn(state.videoPlayer.player, 'getVolume').and.callThrough(); }); it('set the player volume', function () { @@ -841,7 +826,7 @@ function (VideoPlayer) { ['iPad', 'Android', 'iPhone'], function (index, device) { - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); @@ -851,7 +836,7 @@ function (VideoPlayer) { }); it('modules are not initialized on iPhone', function () { - window.onTouchBasedDevice.andReturn(['iPhone']); + window.onTouchBasedDevice.and.returnValue(['iPhone']); state = jasmine.initializePlayer(); state.videoEl = $('video, iframe'); @@ -870,34 +855,28 @@ function (VideoPlayer) { var message = 'controls become visible after playing starts ' + 'on ' + device; - it(message, function () { + it(message, function (done) { var controls; - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); - runs(function () { - state = jasmine.initializePlayer(); - state.videoEl = $('video, iframe'); - controls = state.el.find('.video-controls'); - }); + state = jasmine.initializePlayer(); + state.videoEl = $('video, iframe'); + controls = state.el.find('.video-controls'); - waitsFor(function () { + jasmine.waitUntil(function () { return state.el.hasClass('is-initialized'); - },'Video is not initialized.' , WAIT_TIMEOUT); - - runs(function () { + }).then(function () { expect(controls).toHaveClass('is-hidden'); state.videoPlayer.play(); - }); - - waitsFor(function () { - var duration = state.videoPlayer.duration(); - - return duration > 0 && state.videoPlayer.isPlaying(); - },'Video does not play.' , WAIT_TIMEOUT); - - runs(function () { - expect(controls).not.toHaveClass('is-hidden'); + jasmine.waitUntil(function () { + // Firefox does not return duration for videos until they have reached the end. + // var duration = state.videoPlayer.duration(); + // return duration > 0 && state.videoPlayer.isPlaying(); + return state.videoPlayer.isPlaying(); + }).then(function () { + expect(controls).not.toHaveClass('is-hidden'); + }).always(done); }); }); }); @@ -916,13 +895,13 @@ function (VideoPlayer) { setPlaybackRate: jasmine.createSpy(), player: jasmine.createSpyObj('player', ['setPlaybackRate']) }, - isFlashMode: jasmine.createSpy().andReturn(false) + isFlashMode: jasmine.createSpy().and.returnValue(false) }; }); describe('always', function () { it('convert the current time to the new speed', function () { - state.isFlashMode.andReturn(true); + state.isFlashMode.and.returnValue(true); VideoPlayer.prototype.onSpeedChange.call(state, '0.75', false); expect(state.videoPlayer.currentTime).toBe('120.000'); }); @@ -939,17 +918,17 @@ function (VideoPlayer) { describe('setPlaybackRate', function () { beforeEach(function () { state = { - youtubeId: jasmine.createSpy().andReturn('videoId'), - isFlashMode: jasmine.createSpy().andReturn(false), - isHtml5Mode: jasmine.createSpy().andReturn(true), - isYoutubeType: jasmine.createSpy().andReturn(true), + youtubeId: jasmine.createSpy().and.returnValue('videoId'), + isFlashMode: jasmine.createSpy().and.returnValue(false), + isHtml5Mode: jasmine.createSpy().and.returnValue(true), + isYoutubeType: jasmine.createSpy().and.returnValue(true), setPlayerMode: jasmine.createSpy(), trigger: jasmine.createSpy(), videoPlayer: { currentTime: 60, isPlaying: jasmine.createSpy(), seekTo: jasmine.createSpy(), - duration: jasmine.createSpy().andReturn(60), + duration: jasmine.createSpy().and.returnValue(60), updatePlayTime: jasmine.createSpy(), setPlaybackRate: jasmine.createSpy(), player: jasmine.createSpyObj('player', [ @@ -960,9 +939,9 @@ function (VideoPlayer) { }); it('in Flash mode and video is playing', function () { - state.isFlashMode.andReturn(true); - state.isHtml5Mode.andReturn(false); - state.videoPlayer.isPlaying.andReturn(true); + state.isFlashMode.and.returnValue(true); + state.isHtml5Mode.and.returnValue(false); + state.videoPlayer.isPlaying.and.returnValue(true); VideoPlayer.prototype.setPlaybackRate.call(state, '0.75'); expect(state.videoPlayer.updatePlayTime).toHaveBeenCalledWith(60); expect(state.videoPlayer.player.loadVideoById) @@ -970,9 +949,9 @@ function (VideoPlayer) { }); it('in Flash mode and video not started', function () { - state.isFlashMode.andReturn(true); - state.isHtml5Mode.andReturn(false); - state.videoPlayer.isPlaying.andReturn(false); + state.isFlashMode.and.returnValue(true); + state.isHtml5Mode.and.returnValue(false); + state.videoPlayer.isPlaying.and.returnValue(false); VideoPlayer.prototype.setPlaybackRate.call(state, '0.75'); expect(state.videoPlayer.updatePlayTime).toHaveBeenCalledWith(60); expect(state.videoPlayer.seekTo).toHaveBeenCalledWith(60); @@ -986,7 +965,7 @@ function (VideoPlayer) { }); it('in HTML5 mode', function () { - state.isYoutubeType.andReturn(false); + state.isYoutubeType.and.returnValue(false); VideoPlayer.prototype.setPlaybackRate.call(state, '0.75'); expect(state.videoPlayer.player.setPlaybackRate).toHaveBeenCalledWith('0.75'); }); @@ -994,7 +973,7 @@ function (VideoPlayer) { it('Youtube video in FF, with new speed equal 1.0', function () { state.browserIsFirefox = true; - state.videoPlayer.isPlaying.andReturn(false); + state.videoPlayer.isPlaying.and.returnValue(false); VideoPlayer.prototype.setPlaybackRate.call(state, '1.0'); expect(state.videoPlayer.updatePlayTime).toHaveBeenCalledWith(60); expect(state.videoPlayer.player.cueVideoById) diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_poster_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_poster_spec.js index 18a6f6874c..d2505a11c7 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_poster_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_poster_spec.js @@ -6,7 +6,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); state = jasmine.initializePlayer('video_with_bumper.html'); }); @@ -27,11 +27,11 @@ expect($('.btn-play')).toExist(); }); - it('can start playing the video on click', function () { + it('can start playing the video on click', function (done) { $('.btn-play').click(); - waitsFor(function () { + jasmine.waitUntil(function() { return state.el.hasClass('is-playing'); - }, 'Player is not playing.', WAIT_TIMEOUT); + }).done(done); }); it('destroy itself on "play" event', function () { diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js index 491e98fae7..32cf02ba74 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js @@ -5,7 +5,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); }); afterEach(function () { @@ -18,26 +18,25 @@ describe('constructor', function () { describe('on a non-touch based device', function () { beforeEach(function () { - spyOn($.fn, 'slider').andCallThrough(); + spyOn($.fn, 'slider').and.callThrough(); state = jasmine.initializePlayer(); }); it('build the slider', function () { - expect(state.videoProgressSlider.slider).toBe('.slider'); + expect($('.slider')).toContain(state.videoProgressSlider.slider); expect($.fn.slider).toHaveBeenCalledWith({ range: 'min', min: 0, max: null, - change: state.videoProgressSlider.onChange, slide: state.videoProgressSlider.onSlide, stop: state.videoProgressSlider.onStop }); }); it('build the seek handle', function () { - expect(state.videoProgressSlider.handle) - .toBe('.slider .ui-slider-handle'); + expect($('.ui-slider-handle')) + .toContain(state.videoProgressSlider.handle); }); it('add ARIA attributes to time control', function () { @@ -56,7 +55,7 @@ describe('on a touch-based device', function () { it('does not build the slider on iPhone', function () { - window.onTouchBasedDevice.andReturn(['iPhone']); + window.onTouchBasedDevice.and.returnValue(['iPhone']); state = jasmine.initializePlayer(); @@ -67,7 +66,7 @@ }); $.each(['iPad', 'Android'], function (index, device) { it('build the slider on ' + device, function () { - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); state = jasmine.initializePlayer(); @@ -87,12 +86,12 @@ beforeEach(function () { spy = spyOn(state.videoProgressSlider, 'buildSlider'); - spy.andCallThrough(); + spy.and.callThrough(); state.videoPlayer.play(); }); it('does not build the slider', function () { - expect(spy.callCount).toEqual(0); + expect(spy.calls.count()).toEqual(0); }); }); @@ -106,7 +105,7 @@ describe('when frozen', function () { beforeEach(function () { - spyOn($.fn, 'slider').andCallThrough(); + spyOn($.fn, 'slider').and.callThrough(); state.videoProgressSlider.frozen = true; state.videoProgressSlider.updatePlayTime(20, 120); }); @@ -118,7 +117,7 @@ describe('when not frozen', function () { beforeEach(function () { - spyOn($.fn, 'slider').andCallThrough(); + spyOn($.fn, 'slider').and.callThrough(); state.videoProgressSlider.frozen = false; state.videoProgressSlider.updatePlayTime({ time: 20, @@ -149,8 +148,8 @@ beforeEach(function () { state = jasmine.initializePlayer(); - spyOn($.fn, 'slider').andCallThrough(); - spyOn(state.videoPlayer, 'onSlideSeek').andCallThrough(); + spyOn($.fn, 'slider').and.callThrough(); + spyOn(state.videoPlayer, 'onSlideSeek').and.callThrough(); }); // Disabled 12/30/13 due to flakiness in master @@ -175,11 +174,15 @@ describe('onStop', function () { beforeEach(function () { - jasmine.Clock.useMock(); + jasmine.clock().install(); state = jasmine.initializePlayer(); - spyOn(state.videoPlayer, 'onSlideSeek').andCallThrough(); + spyOn(state.videoPlayer, 'onSlideSeek').and.callThrough(); + }); + + afterEach(function () { + jasmine.clock().uninstall(); }); // Disabled 12/30/13 due to flakiness in master @@ -206,7 +209,7 @@ jQuery.Event('stop'), { value: 20 } ); - jasmine.Clock.tick(200); + jasmine.clock().tick(200); expect(state.videoProgressSlider.frozen).toBeFalsy(); }); @@ -255,7 +258,7 @@ spyOnEvent(state.videoProgressSlider.handle, 'focus'); spyOn(state.videoProgressSlider, 'notifyThroughHandleEnd') - .andCallThrough(); + .and.callThrough(); }); it('params.end = true', function () { @@ -280,17 +283,14 @@ ); }); - it('is called when video plays', function () { + it('is called when video plays', function (done) { state.videoPlayer.play(); - - waitsFor(function () { + jasmine.waitUntil(function() { return state.videoPlayer.isPlaying(); - }, 'duration is set, video is playing', 5000); + }).done(function() { + expect(state.videoProgressSlider.notifyThroughHandleEnd).toHaveBeenCalledWith({end: false}); + }).always(done); - runs(function () { - expect(state.videoProgressSlider.notifyThroughHandleEnd) - .toHaveBeenCalledWith({end: false}); - }); }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_quality_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_quality_control_spec.js index 5ce7375aee..251c59e8fa 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_quality_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_quality_control_spec.js @@ -19,7 +19,7 @@ // Define empty methods in YouTube stub player.quality = 'large'; - player.setPlaybackQuality.andCallFake(function (quality){ + player.setPlaybackQuality.and.callFake(function (quality){ player.quality = quality; }); }); @@ -46,13 +46,13 @@ }); it('calls fetchAvailableQualities only once', function () { - expect(player.getAvailableQualityLevels.calls.length) + expect(player.getAvailableQualityLevels.calls.count()) .toEqual(0); videoPlayer.onPlay(); videoPlayer.onPlay(); - expect(player.getAvailableQualityLevels.calls.length) + expect(player.getAvailableQualityLevels.calls.count()) .toEqual(1); }); @@ -71,7 +71,7 @@ it('leaves quality control hidden on play if HD is not available', function () { - player.getAvailableQualityLevels.andReturn( + player.getAvailableQualityLevels.and.returnValue( ['large', 'medium', 'small'] ); @@ -94,7 +94,7 @@ it('quality control is active if HD is available', function () { - player.getAvailableQualityLevels.andReturn( + player.getAvailableQualityLevels.and.returnValue( ['highres', 'hd1080', 'hd720'] ); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_save_state_plugin_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_save_state_plugin_spec.js index 7c101cdb32..85d174b215 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_save_state_plugin_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_save_state_plugin_spec.js @@ -7,14 +7,14 @@ oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine .createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); - jasmine.stubRequests(); state = jasmine.initializePlayer(); spyOn(state.storage, 'setItem'); }); afterEach(function () { + $('source').remove(); window.onTouchBasedDevice = oldOTBD; state.storage.clear(); @@ -41,7 +41,7 @@ beforeEach(function () { state.videoPlayer.currentTime = videoPlayerCurrentTime; - spyOn(Time, 'formatFull').andCallThrough(); + spyOn(window.Time, 'formatFull').and.callThrough(); }); it('data is not an object, async is true', function () { @@ -172,7 +172,7 @@ }); it('can save state on page unload', function () { - $.ajax.reset(); + $.ajax.calls.reset(); state.videoSaveStatePlugin.onUnload(); expect($.ajax).toHaveBeenCalledWith({ url: state.config.saveStateUrl, @@ -212,7 +212,7 @@ it('can destroy itself', function () { var plugin = state.videoSaveStatePlugin; - spyOn($.fn, 'off').andCallThrough(); + spyOn($.fn, 'off').and.callThrough(); state.videoSaveStatePlugin.destroy(); expect(state.videoSaveStatePlugin).toBeUndefined(); expect($.fn.off).toHaveBeenCalledWith({ diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_skip_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_skip_control_spec.js index 1eca712477..2438dce8a2 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_skip_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_skip_control_spec.js @@ -6,10 +6,10 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine - .createSpy('onTouchBasedDevice').andReturn(null); + .createSpy('onTouchBasedDevice').and.returnValue(null); state = jasmine.initializePlayer('video_with_bumper.html'); $('.poster .btn-play').click(); - spyOn(state.bumperState.videoCommands, 'execute').andCallThrough(); + spyOn(state.bumperState.videoCommands, 'execute').and.callThrough(); }); afterEach(function () { diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js index 2ea4a7e365..2a8b5e8b67 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js @@ -6,7 +6,7 @@ beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); }); afterEach(function () { @@ -26,8 +26,8 @@ var secondaryControls = $('.secondary-controls'), li = secondaryControls.find('.video-speeds li'); - expect(secondaryControls).toContain('.speeds'); - expect(secondaryControls).toContain('.video-speeds'); + expect(secondaryControls).toContainElement('.speeds'); + expect(secondaryControls).toContainElement('.video-speeds'); expect(secondaryControls.find('.value').text()) .toBe('1.50x'); expect(li.filter('.is-active')).toHaveData( @@ -36,9 +36,7 @@ expect(li.length).toBe(state.speeds.length); $.each(li.toArray().reverse(), function (index, link) { - expect($(link)).toHaveData( - 'speed', state.speeds[index] - ); + expect($(link).attr('data-speed')).toEqual(state.speeds[index]); expect($(link).find('.speed-option').text()).toBe( state.speeds[index] + 'x' ); @@ -49,7 +47,7 @@ describe('when running on touch based device', function () { $.each(['iPad', 'Android'], function (index, device) { it('is not rendered on' + device, function () { - window.onTouchBasedDevice.andReturn([device]); + window.onTouchBasedDevice.and.returnValue([device]); state = jasmine.initializePlayer(); expect(state.el.find('.speeds')).not.toExist(); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_storage_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_storage_spec.js index 4a65e83c6f..8cbe133dbb 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_storage_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_storage_spec.js @@ -19,7 +19,7 @@ function (VideoStorage) { }); it('without namespace and id', function () { - spyOn(Number.prototype, 'toString').andReturn('0.abcdedg'); + spyOn(Number.prototype, 'toString').and.returnValue('0.abcdedg'); var storage = VideoStorage(); expect(window.VideoStorage).toBeDefined(); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_volume_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_volume_control_spec.js index 5c3f782e85..21037c2d9c 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_volume_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_volume_control_spec.js @@ -12,7 +12,7 @@ describe('VideoVolumeControl', function () { beforeEach(function () { oldOTBD = window.onTouchBasedDevice; window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice') - .andReturn(null); + .and.returnValue(null); }); afterEach(function () { @@ -23,7 +23,7 @@ describe('VideoVolumeControl', function () { }); it('Volume level has correct value even if cookie is broken', function () { - $.cookie.andReturn('broken_cookie'); + $.cookie.and.returnValue('broken_cookie'); state = jasmine.initializePlayer(); volumeControl = state.videoVolumeControl; expect(volumeControl.volume).toEqual(100); @@ -31,8 +31,8 @@ describe('VideoVolumeControl', function () { describe('constructor', function () { beforeEach(function () { - spyOn($.fn, 'slider').andCallThrough(); - $.cookie.andReturn('75'); + spyOn($.fn, 'slider').and.callThrough(); + $.cookie.and.returnValue('75'); state = jasmine.initializePlayer(); volumeControl = state.videoVolumeControl; }); @@ -46,7 +46,7 @@ describe('VideoVolumeControl', function () { }); it('create the slider', function () { - expect($.fn.slider.calls[2].args).toEqual([{ + expect($.fn.slider.calls.argsFor(2)).toEqual([{ orientation: 'vertical', range: 'min', min: 0, @@ -94,16 +94,23 @@ describe('VideoVolumeControl', function () { state = jasmine.initializePlayer(); volumeControl = state.videoVolumeControl; - this.addMatchers({ - assertLiveRegionState: function (volume, expectation) { - var region = $('.video-live-region'); + jasmine.addMatchers({ + assertLiveRegionState: function () { + return { + compare: function (actual, volume, expectation) { + var region = $('.video-live-region'); - var getExpectedText = function (text) { - return text + ' Volume.'; + var getExpectedText = function (text) { + return text + ' Volume.'; + }; + + actual.setVolume(volume, true, true); + return { + pass: region.text() === getExpectedText(expectation) + }; + + } }; - - this.actual.setVolume(volume, true, true); - return region.text() === getExpectedText(expectation); } }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/xmodule_spec.js b/common/lib/xmodule/xmodule/js/spec/xmodule_spec.js index 0ae76b7215..35f21c401f 100644 --- a/common/lib/xmodule/xmodule/js/spec/xmodule_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/xmodule_spec.js @@ -36,7 +36,7 @@ window.Video = jasmine.createSpy('Video'); removeVideo = true; } - window.Video.andReturn(videoModule); + window.Video.and.returnValue(videoModule); editCallback = jasmine.createSpy('editCallback'); $(document).on('XModule.loaded.edit', editCallback); @@ -171,7 +171,7 @@ el = 'dummy object'; obj = new XModule.Descriptor(el); - spyOn(obj, 'save').andCallThrough(); + spyOn(obj, 'save').and.callThrough(); }); afterEach(function () { @@ -225,7 +225,7 @@ obj.onUpdate(callback1); obj.onUpdate(callback2); - obj.save.andReturn(testValue); + obj.save.and.returnValue(testValue); obj.update(); expect(callback1).toHaveBeenCalledWith(testValue); diff --git a/common/static/coffee/spec/discussion/discussion_spec_helper.coffee b/common/static/coffee/spec/discussion/discussion_spec_helper.coffee index 0b052bc7ba..bea233e0b5 100644 --- a/common/static/coffee/spec/discussion/discussion_spec_helper.coffee +++ b/common/static/coffee/spec/discussion/discussion_spec_helper.coffee @@ -13,7 +13,7 @@ class @DiscussionSpecHelper DiscussionUtil.roleIds["Moderator"].push(parseInt(DiscussionUtil.getUser().id)) @makeAjaxSpy = (fakeAjax) -> - spyOn($, "ajax").andCallFake( + spyOn($, "ajax").and.callFake( (params) -> fakeAjax(params) {always: ->} diff --git a/common/static/coffee/spec/discussion/utils_spec.coffee b/common/static/coffee/spec/discussion/utils_spec.coffee index c456855e06..35f4772998 100644 --- a/common/static/coffee/spec/discussion/utils_spec.coffee +++ b/common/static/coffee/spec/discussion/utils_spec.coffee @@ -6,8 +6,8 @@ describe 'DiscussionUtil', -> it "calls through to safeAjax with correct params, and reverts the model in case of failure", -> deferred = $.Deferred() - spyOn($, "ajax").andReturn(deferred) - spyOn(DiscussionUtil, "safeAjax").andCallThrough() + spyOn($, "ajax").and.returnValue(deferred) + spyOn(DiscussionUtil, "safeAjax").and.callThrough() model = new Backbone.Model({hello: false, number: 42}) updates = {hello: "world"} @@ -19,7 +19,7 @@ describe 'DiscussionUtil', -> # the error message callback should be set up correctly spyOn(DiscussionUtil, "discussionAlert") - DiscussionUtil.safeAjax.mostRecentCall.args[0].error() + DiscussionUtil.safeAjax.calls.mostRecent().args[0].error() expect(DiscussionUtil.discussionAlert).toHaveBeenCalledWith("Sorry", "error message") # if the ajax call ends in failure, the model state should be reverted @@ -27,7 +27,7 @@ describe 'DiscussionUtil', -> expect(model.attributes).toEqual({hello: false, number: 42}) it "rolls back the changes if the associated element is disabled", -> - spyOn(DiscussionUtil, "safeAjax").andCallThrough() + spyOn(DiscussionUtil, "safeAjax").and.callThrough() model = new Backbone.Model({hello: false, number: 42}) updates = {hello: "world"} @@ -35,7 +35,7 @@ describe 'DiscussionUtil', -> # This is the element that is disabled/enabled while the ajax request is # in progress $elem = jasmine.createSpyObj('$elem', ['attr']) - $elem.attr.andReturn(true) + $elem.attr.and.returnValue(true) res = DiscussionUtil.updateWithUndo(model, updates, {foo: "bar", $elem:$elem}, "error message") diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_edit_view_spec.js b/common/static/coffee/spec/discussion/view/discussion_thread_edit_view_spec.js index 76487445bd..b319874b1e 100644 --- a/common/static/coffee/spec/discussion/view/discussion_thread_edit_view_spec.js +++ b/common/static/coffee/spec/discussion/view/discussion_thread_edit_view_spec.js @@ -27,7 +27,7 @@ }); testUpdate = function(view, thread, newTopicId, newTopicName) { - spyOn($, 'ajax').andCallFake(function(params) { + spyOn($, 'ajax').and.callFake(function(params) { expect(params.url.path()).toEqual(DiscussionUtil.urlFor('update_thread', 'dummy_id')); expect(params.data.thread_type).toBe('discussion'); expect(params.data.commentable_id).toBe(newTopicId); @@ -35,7 +35,10 @@ params.success(); return {always: function() {}}; }); - view.$el.find('a.topic-title[data-discussion-id="'+newTopicId+'"]').click(); // set new topic + + view.$el.find('a.topic-title').filter(function (idx, el) { + return $(el).data('discussionId') === newTopicId; + }).click(); // set new topic view.$('.edit-post-title').val('changed thread title'); // set new title view.$("label[for$='post-type-discussion']").click(); // set new thread type view.$('.post-update').click(); @@ -62,7 +65,7 @@ testCancel = function(view) { view.$('.post-cancel').click(); expect($('.edit-post-form')).not.toExist(); - } + }; it('can close the view in tab mode', function() { this.createEditView(); @@ -104,11 +107,11 @@ it('can save new data correctly for current discussion id with dots', function () { this.createEditView({topicId: "6.00.1x_General"}); - testUpdate(this.view, this.thread, "6>00'1x\"Basic_Question", "Basic Question"); + testUpdate(this.view, this.thread, "6>00\'1x\"Basic_Question", "Basic Question"); }); it('can save new data correctly for current discussion id with special characters', function () { - this.createEditView({topicId: "6>00'1x\"Basic_Question"}); + this.createEditView({topicId: "6>00\'1x\"Basic_Question"}); testUpdate(this.view, this.thread, "6.00.1x_General", "General"); }); }); diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee index e27436bc01..740bc7ec2b 100644 --- a/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee @@ -131,8 +131,8 @@ describe "DiscussionThreadListView", -> created_at: '2013-04-03T20:05:39Z', }), ] - - spyOn($, "ajax") + deferred = $.Deferred() + spyOn($, "ajax").and.returnValue(deferred); @discussion = new Discussion([]) @view = new DiscussionThreadListView( @@ -143,7 +143,7 @@ describe "DiscussionThreadListView", -> @view.render() setupAjax = (callback) -> - $.ajax.andCallFake( + $.ajax.and.callFake( (params) => if callback callback(params) @@ -162,7 +162,7 @@ describe "DiscussionThreadListView", -> ) expectFilter = (filterVal) -> - $.ajax.andCallFake((params) -> + $.ajax.and.callFake((params) -> _.each(["unread", "unanswered", "flagged"], (paramName)-> if paramName == filterVal expect(params.data[paramName]).toEqual(true) @@ -199,7 +199,7 @@ describe "DiscussionThreadListView", -> expectedGroupId = optionInfo.expectedGroupId @view.$(".forum-nav-filter-cohort-control").val(optionInfo.val).change() expect($.ajax).toHaveBeenCalled() - $.ajax.reset() + $.ajax.calls.reset() ) it "search should clear filter", -> @@ -255,7 +255,7 @@ describe "DiscussionThreadListView", -> sorted_threads = [threads[0], threads[3], threads[2], threads[1]] else if new_type == 'votes' sorted_threads = [threads[3], threads[0], threads[1], threads[2]] - $.ajax.andCallFake((params) => + $.ajax.and.callFake((params) => params.success( {"discussion_data":sorted_threads, page:1, num_pages:1} ) @@ -307,7 +307,7 @@ describe "DiscussionThreadListView", -> testCorrection = (view, correctedText) -> spyOn(view, "addSearchAlert") - $.ajax.andCallFake( + $.ajax.and.callFake( (params) => params.success( {discussion_data: [], page: 42, num_pages: 99, corrected_text: correctedText}, 'success' @@ -319,13 +319,13 @@ describe "DiscussionThreadListView", -> it "adds a search alert when an alternate term was searched", -> testCorrection(@view, "foo") - expect(@view.addSearchAlert.callCount).toEqual(1) - expect(@view.addSearchAlert.mostRecentCall.args[0]).toMatch(/foo/) + expect(@view.addSearchAlert.calls.count()).toEqual(1) + expect(@view.addSearchAlert.calls.mostRecent().args[0]).toMatch(/foo/) it "does not add a search alert when no alternate term was searched", -> testCorrection(@view, null) - expect(@view.addSearchAlert.callCount).toEqual(1) - expect(@view.addSearchAlert.mostRecentCall.args[0]).toMatch(/no threads matched/i) + expect(@view.addSearchAlert.calls.count()).toEqual(1) + expect(@view.addSearchAlert.calls.mostRecent().args[0]).toMatch(/no threads matched/i) it "clears search alerts when a new search is performed", -> spyOn(@view, "clearSearchAlerts") @@ -356,7 +356,7 @@ describe "DiscussionThreadListView", -> describe "username search", -> it "makes correct ajax calls", -> - $.ajax.andCallFake( + $.ajax.and.callFake( (params) => expect(params.data.username).toEqual("testing-username") expect(params.url.path()).toEqual(DiscussionUtil.urlFor("users")) @@ -371,7 +371,7 @@ describe "DiscussionThreadListView", -> setAjaxResults = (threadSuccess, userResult) -> # threadSuccess is a boolean indicating whether the thread search ajax call should succeed # userResult is the value that should be returned as data from the username search ajax call - $.ajax.andCallFake( + $.ajax.and.callFake( (params) => if params.data.text and threadSuccess params.success( @@ -387,14 +387,14 @@ describe "DiscussionThreadListView", -> ) it "gets called after a thread search succeeds", -> - spyOn(@view, "searchForUser").andCallThrough() + spyOn(@view, "searchForUser").and.callThrough() setAjaxResults(true, []) @view.searchFor("gizmo") expect(@view.searchForUser).toHaveBeenCalled() - expect($.ajax.mostRecentCall.args[0].data.username).toEqual("gizmo") + expect($.ajax.calls.mostRecent().args[0].data.username).toEqual("gizmo") it "does not get called after a thread search fails", -> - spyOn(@view, "searchForUser").andCallThrough() + spyOn(@view, "searchForUser").and.callThrough() setAjaxResults(false, []) @view.searchFor("gizmo") expect(@view.searchForUser).not.toHaveBeenCalled() @@ -405,7 +405,7 @@ describe "DiscussionThreadListView", -> @view.searchForUser("dummy") expect($.ajax).toHaveBeenCalled() expect(@view.addSearchAlert).toHaveBeenCalled() - expect(@view.addSearchAlert.mostRecentCall.args[0]).toMatch(/gizmo/) + expect(@view.addSearchAlert.calls.mostRecent().args[0]).toMatch(/gizmo/) it "does not add a search alert when no username was matched", -> spyOn(@view, "addSearchAlert") @@ -581,7 +581,7 @@ describe "DiscussionThreadListView", -> , "Following" ) - expect($.ajax.mostRecentCall.args[0].data.group_id).toBeUndefined(); + expect($.ajax.calls.mostRecent().args[0].data.group_id).toBeUndefined(); it "should get threads for the selected leaf", -> testSelectionRequest( diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_profile_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_profile_view_spec.coffee index eddd792e23..48572f67ae 100644 --- a/common/static/coffee/spec/discussion/view/discussion_thread_profile_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_thread_profile_view_spec.coffee @@ -27,7 +27,7 @@ describe "DiscussionThreadProfileView", -> return thread spyConvertMath = (view) -> - spyOn(view, "convertMath").andCallFake( -> + spyOn(view, "convertMath").and.callFake( -> @model.set('markdownBody', @model.get('body')) ) diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_show_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_show_view_spec.coffee index 14d75321d5..34036d847b 100644 --- a/common/static/coffee/spec/discussion/view/discussion_thread_show_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_thread_show_view_spec.coffee @@ -22,7 +22,7 @@ describe "DiscussionThreadShowView", -> @thread = new Thread(@threadData) @view = new DiscussionThreadShowView({ model: @thread }) @view.setElement($("#fixture-element")) - @spyOn(@view, "convertMath") + spyOn(@view, "convertMath") describe "voting", -> diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee index 813f10c674..510f896a9a 100644 --- a/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee @@ -3,11 +3,12 @@ describe "DiscussionThreadView", -> DiscussionSpecHelper.setUpGlobals() DiscussionSpecHelper.setUnderscoreFixtures() - jasmine.Clock.useMock() + jasmine.clock().install() @threadData = DiscussionViewSpecHelper.makeThreadWithProps({}) @thread = new Thread(@threadData) @discussion = new Discussion(@thread) - spyOn($, "ajax") + deferred = $.Deferred(); + spyOn($, "ajax").and.returnValue(deferred); # Avoid unnecessary boilerplate spyOn(DiscussionThreadShowView.prototype, "convertMath") spyOn(DiscussionContentView.prototype, "makeWmdEditor") @@ -15,8 +16,12 @@ describe "DiscussionThreadView", -> spyOn(DiscussionUtil, "setWmdContent") spyOn(ThreadResponseShowView.prototype, "convertMath") + afterEach -> + $.ajax.calls.reset() + jasmine.clock().uninstall() + renderWithContent = (view, content) -> - $.ajax.andCallFake((params) => + $.ajax.and.callFake((params) => params.success( createAjaxResponseJson(content, false), 'success' @@ -24,7 +29,7 @@ describe "DiscussionThreadView", -> {always: ->} ) view.render() - jasmine.Clock.tick(100) + jasmine.clock().tick(100) renderWithTestResponses = (view, count, options) -> renderWithContent( @@ -85,8 +90,8 @@ describe "DiscussionThreadView", -> postResponse = (view, index) -> testResponseJson = createTestResponseJson(index) responseText = testResponseJson.body - spyOn(view, "getWmdContent").andReturn(responseText) - $.ajax.andCallFake((params) => + spyOn(view, "getWmdContent").and.returnValue(responseText) + $.ajax.and.callFake((params) => expect(params.type).toEqual("POST") expect(params.data.body).toEqual(responseText) params.success( @@ -112,7 +117,7 @@ describe "DiscussionThreadView", -> renderWithTestResponses(view, 1) if mode == "inline" view.expand() - spyOn(DiscussionUtil, "updateWithUndo").andCallFake( + spyOn(DiscussionUtil, "updateWithUndo").and.callFake( (model, updates, safeAjaxParams, errorMsg) -> model.set(updates) ) @@ -240,16 +245,18 @@ describe "DiscussionThreadView", -> expect(@view.$el.find(".responses li").length).toEqual(0) describe "focus", -> - it "sends focus to the conversation when opened", -> + it "sends focus to the conversation when opened", (done) -> DiscussionViewSpecHelper.setNextResponseContent({resp_total: 0, children: []}) @view.render() @view.expand() - waitsFor (-> + self = @ + jasmine.waitUntil(-> # This is the implementation of "toBeFocused". However, simply calling that method # with no wait seems to be flaky. - article = @view.$el.find('.discussion-article') + article = self.view.$el.find('.discussion-article') return article[0] == article[0].ownerDocument.activeElement - ), "conversation did not receive focus", 3000 + ).then -> + done() describe "expand/collapse", -> it "shows/hides appropriate content", -> @@ -269,12 +276,12 @@ describe "DiscussionThreadView", -> @view.render() expect($(".post-body").text()).toEqual(expectedAbbreviation) expect(DiscussionThreadShowView.prototype.convertMath).toHaveBeenCalled() - DiscussionThreadShowView.prototype.convertMath.reset() + DiscussionThreadShowView.prototype.convertMath.calls.reset() @view.expand() expect($(".post-body").text()).toEqual(longBody) expect(DiscussionThreadShowView.prototype.convertMath).toHaveBeenCalled() - DiscussionThreadShowView.prototype.convertMath.reset() + DiscussionThreadShowView.prototype.convertMath.calls.reset() @view.collapse() expect($(".post-body").text()).toEqual(expectedAbbreviation) diff --git a/common/static/coffee/spec/discussion/view/discussion_user_profile_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_user_profile_view_spec.coffee index 989893d64e..98d47d7205 100644 --- a/common/static/coffee/spec/discussion/view/discussion_user_profile_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_user_profile_view_spec.coffee @@ -193,10 +193,11 @@ describe "DiscussionUserProfileView", -> describe "pagination interaction", -> beforeEach -> @view = makeView(makeThreads(3), 1, 2) - spyOn($, "ajax") + deferred = $.Deferred(); + spyOn($, "ajax").and.returnValue(deferred); it "causes updated rendering", -> - $.ajax.andCallFake( + $.ajax.and.callFake( (params) => params.success( discussion_data: [{id: "on_page_42", body: "dummy body"}] @@ -211,7 +212,7 @@ describe "DiscussionUserProfileView", -> it "handles AJAX errors", -> spyOn(DiscussionUtil, "discussionAlert") - $.ajax.andCallFake( + $.ajax.and.callFake( (params) => params.error() {always: ->} diff --git a/common/static/coffee/spec/discussion/view/discussion_view_spec_helper.coffee b/common/static/coffee/spec/discussion/view/discussion_view_spec_helper.coffee index a263903bcc..d3150d7dfd 100644 --- a/common/static/coffee/spec/discussion/view/discussion_view_spec_helper.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_view_spec_helper.coffee @@ -50,7 +50,7 @@ class @DiscussionViewSpecHelper triggerVoteEvent = (view, event, expectedUrl) -> deferred = $.Deferred() - spyOn($, "ajax").andCallFake((params) => + spyOn($, "ajax").and.callFake((params) => expect(params.url.toString()).toEqual(expectedUrl) return deferred ) @@ -80,10 +80,10 @@ class @DiscussionViewSpecHelper button.click() expect(spy).toHaveBeenCalled() - spy.reset() + spy.calls.reset() button.trigger($.Event("keydown", {which: 13})) expect(spy).not.toHaveBeenCalled() - spy.reset() + spy.calls.reset() button.trigger($.Event("keydown", {which: 32})) expect(spy).toHaveBeenCalled() @@ -91,7 +91,7 @@ class @DiscussionViewSpecHelper @checkButtonEvents(view, "toggleVote", ".action-vote") @setNextResponseContent = (content) -> - $.ajax.andCallFake( + $.ajax.and.callFake( (params) => params.success({"content": content}) {always: ->} diff --git a/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee b/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee index 6458c3cb3d..fb9f244897 100644 --- a/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee @@ -4,7 +4,7 @@ describe "NewPostView", -> DiscussionSpecHelper.setUpGlobals() DiscussionSpecHelper.setUnderscoreFixtures() window.$$course_id = "edX/999/test" - spyOn(DiscussionUtil, "makeWmdEditor").andCallFake( + spyOn(DiscussionUtil, "makeWmdEditor").and.callFake( ($content, $local, cls_identifier) -> $local("." + cls_identifier).html("") ) @@ -91,7 +91,7 @@ describe "NewPostView", -> @view.$(".js-post-body textarea").val("dummy body") @view.$(".forum-new-post-form").submit() expect($.ajax).toHaveBeenCalled() - $.ajax.reset() + $.ajax.calls.reset() ) describe "always cohort inline discussions ", -> @@ -209,7 +209,7 @@ describe "NewPostView", -> it "posts to the correct URL", -> topicId = "test_topic" - spyOn($, "ajax").andCallFake( + spyOn($, "ajax").and.callFake( (params) -> expect(params.url.path()).toEqual(DiscussionUtil.urlFor("create_thread", topicId)) {always: ->} diff --git a/common/static/coffee/spec/discussion/view/response_comment_view_spec.coffee b/common/static/coffee/spec/discussion/view/response_comment_view_spec.coffee index 9f641a8b16..c25269ff4e 100644 --- a/common/static/coffee/spec/discussion/view/response_comment_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/response_comment_view_spec.coffee @@ -25,14 +25,14 @@ describe 'ResponseCommentView', -> spyOn(@view.$el, "remove") setAjaxResult = (isSuccess) -> - spyOn($, "ajax").andCallFake( + spyOn($, "ajax").and.callFake( (params) => (if isSuccess then params.success else params.error) {} {always: ->} ) it 'requires confirmation before deleting', -> - spyOn(window, "confirm").andReturn(false) + spyOn(window, "confirm").and.returnValue(false) setAjaxResult(true) @view._delete(@event) expect(window.confirm).toHaveBeenCalled() @@ -50,7 +50,7 @@ describe 'ResponseCommentView', -> @view._delete(@event) expect(@event.preventDefault).toHaveBeenCalled() expect($.ajax).toHaveBeenCalled() - expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/delete') + expect($.ajax.calls.mostRecent().args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/delete') it 'handles ajax errors', -> spyOn(DiscussionUtil, "discussionAlert") @@ -125,7 +125,7 @@ describe 'ResponseCommentView', -> @view.$el.find(".edit-comment-body").html($("")) @view.$el.find(".edit-comment-body textarea").val(@updatedBody) spyOn(@view, 'cancelEdit') - spyOn($, "ajax").andCallFake( + spyOn($, "ajax").and.callFake( (params) => if @ajaxSucceed params.success() @@ -138,8 +138,8 @@ describe 'ResponseCommentView', -> @ajaxSucceed = true @view.update(DiscussionSpecHelper.makeEventSpy()) expect($.ajax).toHaveBeenCalled() - expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update') - expect($.ajax.mostRecentCall.args[0].data.body).toEqual(@updatedBody) + expect($.ajax.calls.mostRecent().args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update') + expect($.ajax.calls.mostRecent().args[0].data.body).toEqual(@updatedBody) expect(@view.model.get("body")).toEqual(@updatedBody) expect(@view.cancelEdit).toHaveBeenCalled() @@ -148,8 +148,8 @@ describe 'ResponseCommentView', -> @ajaxSucceed = false @view.update(DiscussionSpecHelper.makeEventSpy()) expect($.ajax).toHaveBeenCalled() - expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update') - expect($.ajax.mostRecentCall.args[0].data.body).toEqual(@updatedBody) + expect($.ajax.calls.mostRecent().args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update') + expect($.ajax.calls.mostRecent().args[0].data.body).toEqual(@updatedBody) expect(@view.model.get("body")).toEqual(originalBody) expect(@view.cancelEdit).not.toHaveBeenCalled() expect(@view.$(".edit-comment-form-errors *").length).toEqual(1) diff --git a/common/static/coffee/spec/discussion/view/thread_response_show_view_spec.coffee b/common/static/coffee/spec/discussion/view/thread_response_show_view_spec.coffee index d03b42d83a..bdedff4789 100644 --- a/common/static/coffee/spec/discussion/view/thread_response_show_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/thread_response_show_view_spec.coffee @@ -108,6 +108,7 @@ describe "ThreadResponseShowView", -> expect(@view.$(".posted-details").text()).not.toMatch("\sby\s") it "re-renders correctly when endorsement changes", -> + spyOn($, "ajax").and.returnValue($.Deferred()) DiscussionUtil.loadRoles({"Moderator": [parseInt(window.user.id)]}) @thread.set("thread_type", "question") @view.render() @@ -118,6 +119,7 @@ describe "ThreadResponseShowView", -> expect(@view.$(".posted-details").text()).not.toMatch("marked as answer") it "allows a moderator to mark an answer in a question thread", -> + spyOn($, "ajax").and.returnValue($.Deferred()) DiscussionUtil.loadRoles({"Moderator": [parseInt(window.user.id)]}) @thread.set({ "thread_type": "question", @@ -131,6 +133,7 @@ describe "ThreadResponseShowView", -> expect(endorseButton).toHaveClass("is-checked") it "allows the author of a question thread to mark an answer", -> + spyOn($, "ajax").and.returnValue($.Deferred()) @thread.set({ "thread_type": "question", "user_id": window.user.id @@ -199,7 +202,7 @@ describe "ThreadResponseShowView", -> "username": "test_endorser", "time": new Date().toISOString() }) - spyOn(DiscussionUtil, 'urlFor').andReturn('test_endorser_url') + spyOn(DiscussionUtil, 'urlFor').and.returnValue('test_endorser_url') checkUserLink = (element, is_ta, is_staff) -> expect(element.find('a.username').length).toEqual(1) @@ -217,11 +220,11 @@ describe "ThreadResponseShowView", -> checkUserLink($el, false, false) it "renders correctly for a community TA-endorsed response", -> - spyOn(DiscussionUtil, 'isTA').andReturn(true) + spyOn(DiscussionUtil, 'isTA').and.returnValue(true) $el = $('#fixture-element').html(@view.getEndorserDisplay()) checkUserLink($el, true, false) it "renders correctly for a staff-endorsed response", -> - spyOn(DiscussionUtil, 'isStaff').andReturn(true) + spyOn(DiscussionUtil, 'isStaff').and.returnValue(true) $el = $('#fixture-element').html(@view.getEndorserDisplay()) checkUserLink($el, false, true) diff --git a/common/static/coffee/spec/xblock/core_spec.coffee b/common/static/coffee/spec/xblock/core_spec.coffee index 7e7c1e081a..e04184710a 100644 --- a/common/static/coffee/spec/xblock/core_spec.coffee +++ b/common/static/coffee/spec/xblock/core_spec.coffee @@ -28,14 +28,14 @@ describe "XBlock", -> window.TestRuntime = {} @runtimeA = {name: 'runtimeA'} @runtimeZ = {name: 'runtimeZ'} - TestRuntime.vA = jasmine.createSpy().andReturn(@runtimeA) - TestRuntime.vZ = jasmine.createSpy().andReturn(@runtimeZ) + TestRuntime.vA = jasmine.createSpy().and.returnValue(@runtimeA) + TestRuntime.vZ = jasmine.createSpy().and.returnValue(@runtimeZ) window.initFnA = jasmine.createSpy() window.initFnZ = jasmine.createSpy() @fakeChildren = ['list', 'of', 'children'] - spyOn(XBlock, 'initializeXBlocks').andReturn(@fakeChildren) + spyOn(XBlock, 'initializeXBlocks').and.returnValue(@fakeChildren) @vANode = $('#vA')[0] @vZNode = $('#vZ')[0] @@ -54,11 +54,11 @@ describe "XBlock", -> expect(window.initFnZ).toHaveBeenCalledWith(@runtimeZ, @vZNode, {}) it "loads when missing versions", -> - expect(@missingVersionBlock.element).toBe($('#missing-version')) + expect(@missingVersionBlock.element).toBe($('#missing-version')[0]) expect(@missingVersionBlock.name).toBe('no-version') it "loads when missing init fn", -> - expect(@missingInitBlock.element).toBe($('#missing-init')) + expect(@missingInitBlock.element).toBe($('#missing-init')[0]) expect(@missingInitBlock.name).toBe('no-init') it "adds names to blocks", -> diff --git a/common/static/common/js/spec/components/feedback_spec.js b/common/static/common/js/spec/components/feedback_spec.js index 9ed52894ce..d9703a9979 100644 --- a/common/static/common/js/spec/components/feedback_spec.js +++ b/common/static/common/js/spec/components/feedback_spec.js @@ -1,10 +1,17 @@ // Generated by CoffeeScript 1.6.1 (function() { - - define(["jquery", "common/js/components/views/feedback", "common/js/components/views/feedback_notification", "common/js/components/views/feedback_alert", "common/js/components/views/feedback_prompt", 'common/js/spec_helpers/view_helpers', "sinon", "jquery.simulate"], + 'use strict'; + define(["jquery", "common/js/components/views/feedback", "common/js/components/views/feedback_notification", + "common/js/components/views/feedback_alert", "common/js/components/views/feedback_prompt", + 'common/js/spec_helpers/view_helpers', "sinon", "jquery.simulate", "jasmine-waituntil"], function($, SystemFeedback, NotificationView, AlertView, PromptView, ViewHelpers, sinon) { var tpl; - tpl = readFixtures('system-feedback.underscore'); + tpl = readFixtures('common/templates/components/system-feedback.underscore'); + + var isFocused = function(actual) { + return $(actual)[0] === $(actual)[0].ownerDocument.activeElement; + }; + beforeEach(function() { setFixtures(sandbox({ id: "page-alert" @@ -19,30 +26,24 @@ id: "system-feedback-tpl", type: "text/template" }).text(tpl)); - return this.addMatchers({ + return jasmine.addMatchers({ toBeShown: function() { - return this.actual.hasClass("is-shown") && !this.actual.hasClass("is-hiding"); + return { + compare: function (actual) { + return { + pass: actual.hasClass("is-shown") && !actual.hasClass("is-hiding") + }; + } + }; }, toBeHiding: function() { - return this.actual.hasClass("is-hiding") && !this.actual.hasClass("is-shown"); - }, - toContainText: function(text) { - var trimmedText; - trimmedText = $.trim(this.actual.text()); - if (text && $.isFunction(text.test)) { - return text.test(trimmedText); - } else { - return trimmedText.indexOf(text) !== -1; - } - }, - toHaveBeenPrevented: function() { - var eventName, selector; - eventName = this.actual.eventName; - selector = this.actual.selector; - this.message = function() { - return ["Expected event " + eventName + " to have been prevented on " + selector, "Expected event " + eventName + " not to have been prevented on " + selector]; + return { + compare: function (actual) { + return { + pass: actual.hasClass("is-hiding") && !actual.hasClass("is-shown") + }; + } }; - return jasmine.JQuery.events.wasPrevented(selector, eventName); } }); }); @@ -52,9 +53,9 @@ title: "Portal", message: "Welcome to the Aperture Science Computer-Aided Enrichment Center" }; - this.renderSpy = spyOn(AlertView.Confirmation.prototype, 'render').andCallThrough(); - this.showSpy = spyOn(AlertView.Confirmation.prototype, 'show').andCallThrough(); - this.hideSpy = spyOn(AlertView.Confirmation.prototype, 'hide').andCallThrough(); + this.renderSpy = spyOn(AlertView.Confirmation.prototype, 'render').and.callThrough(); + this.showSpy = spyOn(AlertView.Confirmation.prototype, 'show').and.callThrough(); + this.hideSpy = spyOn(AlertView.Confirmation.prototype, 'hide').and.callThrough(); return this.clock = sinon.useFakeTimers(); }); afterEach(function() { @@ -122,30 +123,35 @@ actions: { primary: { text: "Yes, I'm sure.", - "class": "confirm-button", + "class": "confirm-button" }, secondary: { text: "Cancel", - "class": "cancel-button", + "class": "cancel-button" } } - } - this.inFocusSpy = spyOn(PromptView.Confirmation.prototype, 'inFocus').andCallThrough(); - return this.outFocusSpy = spyOn(PromptView.Confirmation.prototype, 'outFocus').andCallThrough(); + }; + this.inFocusSpy = spyOn(PromptView.Confirmation.prototype, 'inFocus').and.callThrough(); + this.outFocusSpy = spyOn(PromptView.Confirmation.prototype, 'outFocus').and.callThrough(); }); - it("is focused on show", function() { + it("is focused on show", function(done) { var view; view = new PromptView.Confirmation(this.options).show(); expect(this.inFocusSpy).toHaveBeenCalled(); - return ViewHelpers.verifyElementInFocus(view, ".wrapper-prompt") + jasmine.waitUntil(function () { + return isFocused(view.$(".wrapper-prompt")); + }).always(done); }); - it("is not focused on hide", function() { + it("is not focused on hide", function(done) { var view; view = new PromptView.Confirmation(this.options).hide(); expect(this.outFocusSpy).toHaveBeenCalled(); - return ViewHelpers.verifyElementNotInFocus(view, ".wrapper-prompt") + + jasmine.waitUntil(function () { + return !isFocused(view.$(".wrapper-prompt")); + }).always(done); }); - it("traps keyboard focus when moving forward", function() { + it("traps keyboard focus when moving forward", function(done) { var view; view = new PromptView.Confirmation(this.options).show(); expect(this.inFocusSpy).toHaveBeenCalled(); @@ -153,9 +159,12 @@ "keydown", { keyCode: $.simulate.keyCode.TAB } ); - return ViewHelpers.verifyElementInFocus(view, ".action-primary") + + jasmine.waitUntil(function () { + return isFocused(view.$(".action-primary")); + }).always(done); }); - it("traps keyboard focus when moving backward", function() { + it("traps keyboard focus when moving backward", function(done) { var view; view = new PromptView.Confirmation(this.options).show(); expect(this.inFocusSpy).toHaveBeenCalled(); @@ -163,7 +172,9 @@ "keydown", { keyCode: $.simulate.keyCode.TAB, shiftKey: true } ); - return ViewHelpers.verifyElementInFocus(view, ".action-secondary") + jasmine.waitUntil(function () { + return isFocused(view.$(".action-secondary")); + }).always(done); }); return it("changes class on body", function() { var view; @@ -175,14 +186,15 @@ }); }); describe("NotificationView.Mini", function() { + var view; beforeEach(function() { - return this.view = new NotificationView.Mini(); + view = new NotificationView.Mini(); }); it("should have minShown set to 1250 by default", function() { - return expect(this.view.options.minShown).toEqual(1250); + return expect(view.options.minShown).toEqual(1250); }); return it("should have closeIcon set to false by default", function() { - return expect(this.view.options.closeIcon).toBeFalsy(); + return expect(view.options.closeIcon).toBeFalsy(); }); }); xdescribe("SystemFeedback click events", function() { @@ -301,9 +313,9 @@ return describe("NotificationView minShown and maxShown", function() { beforeEach(function() { this.showSpy = spyOn(NotificationView.Confirmation.prototype, 'show'); - this.showSpy.andCallThrough(); + this.showSpy.and.callThrough(); this.hideSpy = spyOn(NotificationView.Confirmation.prototype, 'hide'); - this.hideSpy.andCallThrough(); + this.hideSpy.and.callThrough(); return this.clock = sinon.useFakeTimers(); }); afterEach(function() { diff --git a/common/static/common/js/spec/main_requirejs.js b/common/static/common/js/spec/main_requirejs.js index 13b7349648..ec2930ce8b 100644 --- a/common/static/common/js/spec/main_requirejs.js +++ b/common/static/common/js/spec/main_requirejs.js @@ -36,7 +36,9 @@ 'edxicons': 'edx-pattern-library/js/edx-icons', 'draggabilly': 'js/vendor/draggabilly', 'jasmine-stealth': 'js/libs/jasmine-stealth', - 'jasmine-waituntil': 'js/libs/jasmine-waituntil' + 'jasmine-waituntil': 'js/libs/jasmine-waituntil', + 'jasmine-extensions': 'js/libs/jasmine-extensions', + 'URI': 'js/vendor/URI.min' }, shim: { 'gettext': { @@ -145,6 +147,9 @@ 'jasmine-waituntil': { deps: ['jquery'] }, + 'jasmine-extensions': { + deps: ['jquery'] + }, "sinon": { exports: "sinon" }, diff --git a/common/static/common/js/spec_helpers/ajax_helpers.js b/common/static/common/js/spec_helpers/ajax_helpers.js index 056328e07e..253c94595d 100644 --- a/common/static/common/js/spec_helpers/ajax_helpers.js +++ b/common/static/common/js/spec_helpers/ajax_helpers.js @@ -28,10 +28,12 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) { * Get a reference to the mocked server, and respond * to all requests with the specified statusCode. */ - fakeServer = function (that, response) { + fakeServer = function (response) { var server = sinon.fakeServer.create(); - that.after(function() { - server.restore(); + afterEach(function() { + if (server) { + server.restore(); + } }); server.respondWith(response); return server; @@ -42,16 +44,19 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) { * return a reference to the Array. This allows tests * to respond for individual requests. */ - fakeRequests = function (that) { + fakeRequests = function () { var requests = [], - xhr = sinon.useFakeXMLHttpRequest(); + xhr = sinon.useFakeXMLHttpRequest(); + requests.currentIndex = 0; xhr.onCreate = function(request) { requests.push(request); }; - that.after(function() { - xhr.restore(); + afterEach(function() { + if (xhr && xhr.hasOwnProperty('restore')) { + xhr.restore(); + } }); return requests; }; @@ -88,11 +93,12 @@ define(['sinon', 'underscore', 'URI'], function(sinon, _, URI) { }; expectJsonRequest = function(requests, method, url, jsonRequest) { + jsonRequest = jsonRequest || null; var request = currentRequest(requests); expect(request.readyState).toEqual(XML_HTTP_READY_STATES.OPENED); expect(request.url).toEqual(url); expect(request.method).toEqual(method); - expect(JSON.parse(request.requestBody)).toEqual(jsonRequest); + expect(JSON.parse(request.requestBody)).toEqual(jsonRequest === undefined ? null : jsonRequest); }; /** diff --git a/common/static/common/js/spec_helpers/page_helpers.js b/common/static/common/js/spec_helpers/page_helpers.js index 033f0e9b6d..dec87b50c9 100644 --- a/common/static/common/js/spec_helpers/page_helpers.js +++ b/common/static/common/js/spec_helpers/page_helpers.js @@ -32,12 +32,12 @@ define(["backbone"], }; // Stub out the Backbone router so that the browser doesn't actually navigate - spyOn(Backbone.history, '_updateHash').andCallFake(function (location, fragment, replace) { + spyOn(Backbone.history, '_updateHash').and.callFake(function (location, fragment) { history.currentFragment = fragment; }); // Stub out getHash so that Backbone thinks that the browser has navigated - spyOn(Backbone.history, 'getHash').andCallFake(function () { + spyOn(Backbone.history, 'getHash').and.callFake(function () { return history.currentFragment; }); }; diff --git a/common/static/common/js/spec_helpers/view_helpers.js b/common/static/common/js/spec_helpers/view_helpers.js index 93b5827b89..f86d2bc206 100644 --- a/common/static/common/js/spec_helpers/view_helpers.js +++ b/common/static/common/js/spec_helpers/view_helpers.js @@ -10,16 +10,18 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js verifyFeedbackHidden, createNotificationSpy, verifyNotificationShowing, verifyNotificationHidden, createPromptSpy, confirmPrompt, inlineEdit, verifyInlineEditChange, installMockAnalytics, removeMockAnalytics, verifyPromptShowing, verifyPromptHidden, - clickDeleteItem, patchAndVerifyRequest, submitAndVerifyFormSuccess, submitAndVerifyFormError, - verifyElementInFocus, verifyElementNotInFocus; + clickDeleteItem, patchAndVerifyRequest, submitAndVerifyFormSuccess, submitAndVerifyFormError; installViewTemplates = function() { appendSetFixtures(''); }; createFeedbackSpy = function(type, intent) { - var feedbackSpy = spyOnConstructor(type, intent, ['show', 'hide']); - feedbackSpy.show.andReturn(feedbackSpy); + var feedbackSpy = jasmine.stealth.spyOnConstructor(type, intent, ['show', 'hide']); + feedbackSpy.show.and.returnValue(feedbackSpy); + if (afterEach) { + afterEach(jasmine.stealth.clearSpies); + } return feedbackSpy; }; @@ -28,7 +30,7 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js expect(feedbackSpy.constructor).toHaveBeenCalled(); expect(feedbackSpy.show).toHaveBeenCalled(); expect(feedbackSpy.hide).not.toHaveBeenCalled(); - options = feedbackSpy.constructor.mostRecentCall.args[0]; + options = feedbackSpy.constructor.calls.mostRecent().args[0]; expect(options.title).toMatch(text); }; @@ -55,9 +57,9 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js confirmPrompt = function(promptSpy, pressSecondaryButton) { expect(promptSpy.constructor).toHaveBeenCalled(); if (pressSecondaryButton) { - promptSpy.constructor.mostRecentCall.args[0].actions.secondary.click(promptSpy); + promptSpy.constructor.calls.mostRecent().args[0].actions.secondary.click(promptSpy); } else { - promptSpy.constructor.mostRecentCall.args[0].actions.primary.click(promptSpy); + promptSpy.constructor.calls.mostRecent().args[0].actions.primary.click(promptSpy); } }; @@ -128,22 +130,6 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js verifyNotificationShowing(notificationSpy, /Saving/); }; - verifyElementInFocus = function(view, selector) { - waitsFor( - function() { return view.$(selector + ':focus').length === 1; }, - "element to have focus: " + selector, - 500 - ); - }; - - verifyElementNotInFocus = function(view, selector) { - waitsFor( - function() { return view.$(selector + ':focus').length === 0; }, - "element to not have focus: " + selector, - 500 - ); - }; - return { 'installViewTemplates': installViewTemplates, 'createNotificationSpy': createNotificationSpy, @@ -160,9 +146,7 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js 'clickDeleteItem': clickDeleteItem, 'patchAndVerifyRequest': patchAndVerifyRequest, 'submitAndVerifyFormSuccess': submitAndVerifyFormSuccess, - 'submitAndVerifyFormError': submitAndVerifyFormError, - 'verifyElementInFocus': verifyElementInFocus, - 'verifyElementNotInFocus': verifyElementNotInFocus + 'submitAndVerifyFormError': submitAndVerifyFormError }; }); }).call(this, define || RequireJS.define); diff --git a/common/static/js/capa/spec/formula_equation_preview_spec.js b/common/static/js/capa/spec/formula_equation_preview_spec.js index 4360d7513b..7a115ed9ce 100644 --- a/common/static/js/capa/spec/formula_equation_preview_spec.js +++ b/common/static/js/capa/spec/formula_equation_preview_spec.js @@ -1,15 +1,6 @@ -function callPeriodicallyUntil(block, delay, condition, i) { // i is optional - i = i || 0; - block(i); - waits(delay); - runs(function () { - if (!condition()) { - callPeriodicallyUntil(block, delay, condition, i + 1); - } - }); -} - describe("Formula Equation Preview", function () { + 'use strict'; + var formulaEquationPreview = window.formulaEquationPreview; beforeEach(function () { // Simulate an environment conducive to a FormulaEquationInput var $fixture = this.$fixture = $('\ @@ -37,7 +28,7 @@ describe("Formula Equation Preview", function () { // Call old function. return old$find.apply(this, arguments); - } + }; $.find.matchesSelector = old$find.matchesSelector; this.oldDGEBI = document.getElementById; @@ -50,8 +41,8 @@ describe("Formula Equation Preview", function () { this.oldProblem = window.Problem; window.Problem = {}; - Problem.inputAjax = jasmine.createSpy('Problem.inputAjax') - .andCallFake(function () { + window.Problem.inputAjax = jasmine.createSpy('Problem.inputAjax') + .and.callFake(function () { ajaxTimes.push(Date.now()); }); @@ -60,19 +51,19 @@ describe("Formula Equation Preview", function () { this.oldMathJax = window.MathJax; window.MathJax = {Hub: {}}; - MathJax.Hub.getAllJax = jasmine.createSpy('MathJax.Hub.getAllJax') - .andReturn([this.jax]); - MathJax.Hub.Queue = function (callback) { + window.MathJax.Hub.getAllJax = jasmine.createSpy('MathJax.Hub.getAllJax') + .and.returnValue([this.jax]); + window.MathJax.Hub.Queue = function (callback) { if (typeof (callback) == 'function') { callback(); } - } - spyOn(MathJax.Hub, 'Queue').andCallThrough() - MathJax.Hub.Startup = jasmine.createSpy('MathJax.Hub.Startup'); - MathJax.Hub.Startup.signal = jasmine.createSpy('MathJax.Hub.Startup.signal'); - MathJax.Hub.Startup.signal.Interest = function (callback) { + }; + spyOn(window.MathJax.Hub, 'Queue').and.callThrough(); + window.MathJax.Hub.Startup = jasmine.createSpy('MathJax.Hub.Startup'); + window.MathJax.Hub.Startup.signal = jasmine.createSpy('MathJax.Hub.Startup.signal'); + window.MathJax.Hub.Startup.signal.Interest = function (callback) { callback('End'); - } + }; }); it('(the test) is able to swap out the behavior of $', function () { @@ -90,22 +81,22 @@ describe("Formula Equation Preview", function () { }); describe('Ajax requests', function () { - beforeEach(function () { + beforeEach(function (done) { // This is common to all tests on ajax requests. formulaEquationPreview.enable(); // This part may be asynchronous, so wait. - waitsFor(function () { - return Problem.inputAjax.wasCalled; - }, "AJAX never called initially", 1000); + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0; + }).then(done); }); it('has an initial request with the correct parameters', function () { - expect(Problem.inputAjax.callCount).toEqual(1); + expect(window.Problem.inputAjax.calls.count()).toEqual(1); // Use `.toEqual` rather than `.toHaveBeenCalledWith` // since it supports `jasmine.any`. - expect(Problem.inputAjax.mostRecentCall.args).toEqual([ + expect(window.Problem.inputAjax.calls.mostRecent().args).toEqual([ "THE_URL", "THE_ID", "preview_formcalc", @@ -115,65 +106,59 @@ describe("Formula Equation Preview", function () { ]); }); - it('does not request again if the initial request has already been made', function () { + it('does not request again if the initial request has already been made', function (done) { // jshint undef:false - expect(Problem.inputAjax.callCount).toEqual(1); + expect(window.Problem.inputAjax.calls.count()).toEqual(1); // Reset the spy in order to check calls again. - Problem.inputAjax.reset(); + window.Problem.inputAjax.calls.reset(); // Enabling the formulaEquationPreview again to see if this will // reinitialize input request once again. formulaEquationPreview.enable(); // This part may be asynchronous, so wait. - waitsFor(function () { - return !Problem.inputAjax.wasCalled; - }, "times out in case of AJAX call", 1000); - - // Expect Problem.inputAjax was not called as input request was - // initialized before. - expect(Problem.inputAjax).not.toHaveBeenCalled(); + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() === 0; + }).then(function () { + // Expect window.Problem.inputAjax was not called as input request was + // initialized before. + expect(window.Problem.inputAjax).not.toHaveBeenCalled(); + }).always(done); }); - it('makes a request on user input', function () { - Problem.inputAjax.reset(); + it('makes a request on user input', function (done) { + window.Problem.inputAjax.calls.reset(); $('#input_THE_ID').val('user_input').trigger('input'); // This part is probably asynchronous - waitsFor(function () { - return Problem.inputAjax.wasCalled; - }, "AJAX never called on user input", 1000); - - runs(function () { - expect(Problem.inputAjax.mostRecentCall.args[3].formula - ).toEqual('user_input'); - }); + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0; + }).then(function () { + expect(window.Problem.inputAjax.calls.mostRecent().args[3].formula).toEqual('user_input'); + }).always(done); }); - it("isn't requested for empty input", function () { - Problem.inputAjax.reset(); + it("isn't requested for empty input", function (done) { + window.Problem.inputAjax.calls.reset(); // When we make an input of '', $('#input_THE_ID').val('').trigger('input'); // Either it makes a request or jumps straight into displaying ''. - waitsFor(function () { + jasmine.waitUntil(function () { // (Short circuit if `inputAjax` is indeed called) - return Problem.inputAjax.wasCalled || // jshint ignore:line - MathJax.Hub.Queue.wasCalled; - }, "AJAX never called on user input", 1000); - - runs(function () { + return window.Problem.inputAjax.calls.count() > 0 || + window.MathJax.Hub.Queue.calls.count() > 0; + }).then(function () { // Expect the request not to have been called. - expect(Problem.inputAjax).not.toHaveBeenCalled(); - }); + expect(window.Problem.inputAjax).not.toHaveBeenCalled(); + }).always(done); }); - it('limits the number of requests per second', function () { + it('limits the number of requests per second', function (done) { var minDelay = formulaEquationPreview.minDelay; var end = Date.now() + minDelay * 1.1; - var step = 10; // ms var $input = $('#input_THE_ID'); var value; @@ -182,41 +167,42 @@ describe("Formula Equation Preview", function () { $input.val(value).trigger('input'); } - callPeriodicallyUntil(inputAnother, step, function () { + var self = this; + var iter = 0; + jasmine.waitUntil(function () { + inputAnother(iter++); return Date.now() > end; // Stop when we get to `end`. - }); + }).then(function () { + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0 && + window.Problem.inputAjax.calls.mostRecent().args[3].formula === value; + }).then(_.bind(function () { + // There should be 2 or 3 calls (depending on leading edge). + expect(window.Problem.inputAjax.calls.count()).not.toBeGreaterThan(3); - waitsFor(function () { - return Problem.inputAjax.wasCalled && - Problem.inputAjax.mostRecentCall.args[3].formula == value; - }, "AJAX never called with final value from input", 1000); - - runs(function () { - // There should be 2 or 3 calls (depending on leading edge). - expect(Problem.inputAjax.callCount).not.toBeGreaterThan(3); - - // The calls should happen approximately `minDelay` apart. - for (var i =1; i < this.ajaxTimes.length; i ++) { - var diff = this.ajaxTimes[i] - this.ajaxTimes[i - 1]; - expect(diff).toBeGreaterThan(minDelay - 10); - } + // The calls should happen approximately `minDelay` apart. + for (var i =1; i < this.ajaxTimes.length; i ++) { + var diff = this.ajaxTimes[i] - this.ajaxTimes[i - 1]; + expect(diff).toBeGreaterThan(minDelay - 10); + } + }, self)).then(function () { + done(); + }); }); }); }); describe("Visible results (icon and mathjax)", function () { - it('displays a loading icon when requests are open', function () { + it('displays a loading icon when requests are open', function (done) { var $img = $("img.loading"); expect($img.css('visibility')).toEqual('hidden'); formulaEquationPreview.enable(); expect($img.css('visibility')).toEqual('visible'); // This part could be asynchronous - waitsFor(function () { - return Problem.inputAjax.wasCalled; - }, "AJAX never called initially", 1000); - - runs(function () { + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0; + }).then(function () { expect($img.css('visibility')).toEqual('visible'); // Reset and send another request. @@ -224,23 +210,23 @@ describe("Formula Equation Preview", function () { $("#input_THE_ID").val("different").trigger('input'); expect($img.css('visibility')).toEqual('visible'); - }); - - // Don't let it fail later. - waitsFor(function () { - var args = Problem.inputAjax.mostRecentCall.args; - return args[3].formula == "different"; + }).then(function () { + return jasmine.waitUntil(function () { + var args = window.Problem.inputAjax.calls.mostRecent().args; + return args[3].formula === "different"; + }).then(done); }); }); - it('updates MathJax and loading icon on callback', function () { + it('updates MathJax and loading icon on callback', function (done) { formulaEquationPreview.enable(); - waitsFor(function () { - return Problem.inputAjax.wasCalled; - }, "AJAX never called initially", 1000); - runs(function () { - var args = Problem.inputAjax.mostRecentCall.args; + var jax = this.jax; + + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0; + }).then(function () { + var args = window.Problem.inputAjax.calls.mostRecent().args; var callback = args[4]; callback({ preview: 'THE_FORMULA', @@ -252,29 +238,27 @@ describe("Formula Equation Preview", function () { // We should look in the preview div for the MathJax. var previewDiv = $("#input_THE_ID_preview")[0]; - expect(MathJax.Hub.getAllJax).toHaveBeenCalledWith(previewDiv); + expect(window.MathJax.Hub.getAllJax).toHaveBeenCalledWith(previewDiv); // Refresh the MathJax. - expect(MathJax.Hub.Queue).toHaveBeenCalledWith( - ['Text', this.jax, 'THE_FORMULA'] + expect(window.MathJax.Hub.Queue).toHaveBeenCalledWith( + ['Text', jax, 'THE_FORMULA'] ); - }); + }).always(done); }); - it('finds alternatives if MathJax hasn\'t finished loading', function () { + it('finds alternatives if MathJax hasn\'t finished loading', function (done) { formulaEquationPreview.enable(); $('#input_THE_ID').val('user_input').trigger('input'); - waitsFor(function () { - return Problem.inputAjax.wasCalled; - }, "AJAX never called initially", 1000); - - runs(function () { - var args = Problem.inputAjax.mostRecentCall.args; + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0; + }).then(function () { + var args = window.Problem.inputAjax.calls.mostRecent().args; var callback = args[4]; // Cannot find MathJax. - MathJax.Hub.getAllJax.andReturn([]); + window.MathJax.Hub.getAllJax.and.returnValue([]); spyOn(console, 'log'); callback({ @@ -290,74 +274,68 @@ describe("Formula Equation Preview", function () { expect(previewElement.firstChild.data).toEqual("\\(THE_FORMULA\\)"); // Refresh the MathJax. - expect(MathJax.Hub.Queue).toHaveBeenCalledWith( + expect(window.MathJax.Hub.Queue).toHaveBeenCalledWith( ['Typeset', jasmine.any(Object), jasmine.any(Element)] ); - }); + }).always(done); }); - it('displays errors from the server well', function () { + it('displays errors from the server well', function (done) { var $img = $("img.loading"); - formulaEquationPreview.enable(); - waitsFor(function () { - return Problem.inputAjax.wasCalled; - }, "AJAX never called initially", 1000); + var jax = this.jax; - runs(function () { - var args = Problem.inputAjax.mostRecentCall.args; + formulaEquationPreview.enable(); + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0; + }).then(function () { + var args = window.Problem.inputAjax.calls.mostRecent().args; var callback = args[4]; callback({ error: 'OOPSIE', request_start: args[3].request_start }); - expect(MathJax.Hub.Queue).not.toHaveBeenCalled(); + expect(window.MathJax.Hub.Queue).not.toHaveBeenCalled(); expect($img.css('visibility')).toEqual('visible'); - }); - - var errorDelay = formulaEquationPreview.errorDelay * 1.1; - waitsFor(function () { - return MathJax.Hub.Queue.wasCalled; - }, "Error message never displayed", 2000); - - runs(function () { - // Refresh the MathJax. - expect(MathJax.Hub.Queue).toHaveBeenCalledWith( - ['Text', this.jax, '\\text{OOPSIE}'] - ); - expect($img.css('visibility')).toEqual('hidden'); + }).then(function () { + jasmine.waitUntil(function () { + return window.MathJax.Hub.Queue.calls.count() > 0; + }).then(function () { + // Refresh the MathJax. + expect(window.MathJax.Hub.Queue).toHaveBeenCalledWith( + ['Text', jax, '\\text{OOPSIE}'] + ); + expect($img.css('visibility')).toEqual('hidden'); + }).then(done); }); }); }); describe('Multiple callbacks', function () { - beforeEach(function () { + beforeEach(function (done) { formulaEquationPreview.enable(); - waitsFor(function () { - return Problem.inputAjax.wasCalled; - }); - - runs(function () { + var self = this; + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 0; + }).then(function () { $('#input_THE_ID').val('different').trigger('input'); - }); + jasmine.waitUntil(function () { + return window.Problem.inputAjax.calls.count() > 1; + }).then(_.bind(function () { + var args0 = window.Problem.inputAjax.calls.argsFor(0); + var args1 = window.Problem.inputAjax.calls.argsFor(1); + var response0 = { + preview: 'THE_FORMULA_0', + request_start: args0[3].request_start + }; + var response1 = { + preview: 'THE_FORMULA_1', + request_start: args1[3].request_start + }; - waitsFor(function () { - return Problem.inputAjax.callCount > 1; - }); - - runs(function () { - var args = Problem.inputAjax.argsForCall; - var response0 = { - preview: 'THE_FORMULA_0', - request_start: args[0][3].request_start - }; - var response1 = { - preview: 'THE_FORMULA_1', - request_start: args[1][3].request_start - }; - - this.callbacks = [args[0][4], args[1][4]]; - this.responses = [response0, response1]; + this.callbacks = [args0[4], args0[4]]; + this.responses = [response0, response1]; + }, self)).then(done); }); }); @@ -367,13 +345,13 @@ describe("Formula Equation Preview", function () { expect($img.css('visibility')).toEqual('visible'); this.callbacks[0](this.responses[0]); - expect(MathJax.Hub.Queue).toHaveBeenCalledWith( + expect(window.MathJax.Hub.Queue).toHaveBeenCalledWith( ['Text', this.jax, 'THE_FORMULA_0'] ); expect($img.css('visibility')).toEqual('visible'); this.callbacks[1](this.responses[1]); - expect(MathJax.Hub.Queue).toHaveBeenCalledWith( + expect(window.MathJax.Hub.Queue).toHaveBeenCalledWith( ['Text', this.jax, 'THE_FORMULA_1'] ); expect($img.css('visibility')).toEqual('hidden'); @@ -386,40 +364,38 @@ describe("Formula Equation Preview", function () { // Switch the order (1 returns before 0) this.callbacks[1](this.responses[1]); - expect(MathJax.Hub.Queue).toHaveBeenCalledWith( + expect(window.MathJax.Hub.Queue).toHaveBeenCalledWith( ['Text', this.jax, 'THE_FORMULA_1'] ); expect($img.css('visibility')).toEqual('hidden'); - MathJax.Hub.Queue.reset(); + window.MathJax.Hub.Queue.calls.reset(); this.callbacks[0](this.responses[0]); - expect(MathJax.Hub.Queue).not.toHaveBeenCalled(); + expect(window.MathJax.Hub.Queue).not.toHaveBeenCalled(); expect($img.css('visibility')).toEqual('hidden'); }); - it("doesn't show an error if the responses are close together", - function () { - this.callbacks[0]({ - error: 'OOPSIE', - request_start: this.responses[0].request_start - }); - expect(MathJax.Hub.Queue).not.toHaveBeenCalled(); - // Error message waiting to be displayed + it("doesn't show an error if the responses are close together", function (done) { + this.callbacks[0]({ + error: 'OOPSIE', + request_start: this.responses[0].request_start + }); + expect(window.MathJax.Hub.Queue).not.toHaveBeenCalled(); - this.callbacks[1](this.responses[1]); - expect(MathJax.Hub.Queue).toHaveBeenCalledWith( - ['Text', this.jax, 'THE_FORMULA_1'] - ); + // Error message waiting to be displayed + this.callbacks[1](this.responses[1]); + expect(window.MathJax.Hub.Queue).toHaveBeenCalledWith( + ['Text', this.jax, 'THE_FORMULA_1'] + ); - // Make sure that it doesn't indeed show up later - MathJax.Hub.Queue.reset(); - var errorDelay = formulaEquationPreview.errorDelay * 1.1; - waits(errorDelay); - - runs(function () { - expect(MathJax.Hub.Queue).not.toHaveBeenCalled(); - }) - }); + // Make sure that it doesn't indeed show up later + window.MathJax.Hub.Queue.calls.reset(); + jasmine.waitUntil(function () { + return formulaEquationPreview.errorDelay * 1.1; + }).then(function () { + expect(window.MathJax.Hub.Queue).not.toHaveBeenCalled(); + }).then(done); + }); }); afterEach(function () { @@ -428,15 +404,15 @@ describe("Formula Equation Preview", function () { document.getElementById = this.oldDGEBI; // Return Problem - Problem = this.oldProblem; - if (Problem === undefined) { - delete Problem; + window.Problem = this.oldProblem; + if (window.Problem === undefined) { + delete window.Problem; } // Return MathJax - MathJax = this.oldMathJax; - if (MathJax === undefined) { - delete MathJax; + window.MathJax = this.oldMathJax; + if (window.MathJax === undefined) { + delete window.MathJax; } }); }); diff --git a/common/static/js/libs/jasmine-extensions.js b/common/static/js/libs/jasmine-extensions.js new file mode 100644 index 0000000000..47b95619ce --- /dev/null +++ b/common/static/js/libs/jasmine-extensions.js @@ -0,0 +1,248 @@ +// Extensions to Jasmine. +// +// This file adds the following: +// 1. Custom matchers that may be helpful project-wise. +// 2. Copies of some matchers from Jasmine-jQuery. +// Because Jasmine-Jquery uses its own version of JQuery, events registered in the code +// using the platform version of JQuery are not "noticed" by Jasmine-jQuery matchers. +// Similarly equality matching does not work either. So after the platform version of +// jQuery has been loaded, we set these matchers up again in this module. + +(function(root, factory) { + /* jshint strict: false */ + factory(root, root.jQuery); +}((function() { + /* jshint strict: false */ + return this; +}()), function(window, $) { + 'use strict'; + + // Add custom Jasmine matchers. + beforeEach(function() { + + jasmine.addMatchers(window.imagediff.jasmine); + + jasmine.addMatchers({ + toHaveAttrs: function() { + return { + compare: function(actual, attrs) { + var result = {}, + element = actual; + + if ($.isEmptyObject(attrs)) { + return { + pass: false + }; + } + + result.pass = _.every(attrs, function(value, name) { + return element.attr(name) === value; + }); + + return result; + } + }; + }, + toBeInRange: function() { + return { + compare: function(actual, min, max) { + return { + pass: min <= actual && actual <= max + }; + } + }; + }, + toBeInArray: function() { + return { + compare: function(actual, array) { + return { + pass: $.inArray(actual, array) > -1 + }; + } + }; + } + }); + }); + + /* jshint ignore:start */ + // All the code below is taken from: + // https://github.com/velesin/jasmine-jquery/blob/2.1.1/lib/jasmine-jquery.js + beforeEach(function() { + jasmine.addMatchers({ + toHandle: function() { + return { + compare: function(actual, event) { + if (!actual || actual.length === 0) return { + pass: false + }; + var events = $._data($(actual).get(0), "events"); + + if (!events || !event || typeof event !== "string") { + return { + pass: false + }; + } + + var namespaces = event.split("."), + eventType = namespaces.shift(), + sortedNamespaces = namespaces.slice(0).sort(), + namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + if (events[eventType] && namespaces.length) { + for (var i = 0; i < events[eventType].length; i++) { + var namespace = events[eventType][i].namespace; + + if (namespaceRegExp.test(namespace)) + return { + pass: true + }; + } + } else { + return { + pass: (events[eventType] && events[eventType].length > 0) + }; + } + + return { + pass: false + }; + } + }; + }, + + toHandleWith: function() { + return { + compare: function(actual, eventName, eventHandler) { + if (!actual || actual.length === 0) return { + pass: false + }; + var normalizedEventName = eventName.split('.')[0], + stack = $._data($(actual).get(0), "events")[normalizedEventName]; + + for (var i = 0; i < stack.length; i++) { + if (stack[i].handler == eventHandler) return { + pass: true + }; + } + + return { + pass: false + }; + } + }; + } + }); + + jasmine.addCustomEqualityTester(function(a, b) { + if (a && b) { + if (a instanceof $ || jasmine.isDomNode(a)) { + var $a = $(a); + + if (b instanceof $) + return $a.length == b.length && a.is(b); + + return $a.is(b); + } + + if (b instanceof $ || jasmine.isDomNode(b)) { + var $b = $(b); + + if (a instanceof $) + return a.length == $b.length && $b.is(a); + + return $(b).is(a); + } + } + }); + + jasmine.addCustomEqualityTester(function(a, b) { + if (a instanceof $ && b instanceof $ && a.size() == b.size()) + return a.is(b); + }); + + }); + + var data = { + spiedEvents: {}, + handlers: [] + }; + + jasmine.jQuery.events = { + spyOn: function(selector, eventName) { + var handler = function(e) { + var calls = (typeof data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] !== 'undefined') ? data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0; + data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = { + args: jasmine.util.argsToArray(arguments), + calls: ++calls + }; + }; + + $(selector).on(eventName, handler); + data.handlers.push(handler); + + return { + selector: selector, + eventName: eventName, + handler: handler, + reset: function() { + delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]; + }, + calls: { + count: function() { + return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? + data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0; + }, + any: function() { + return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? + !!data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : false; + } + } + }; + }, + + args: function(selector, eventName) { + var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].args; + + if (!actualArgs) { + throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent."; + } + + return actualArgs; + }, + + wasTriggered: function(selector, eventName) { + return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]); + }, + + wasTriggeredWith: function(selector, eventName, expectedArgs, util, customEqualityTesters) { + var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1); + + if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') + actualArgs = actualArgs[0]; + + return util.equals(actualArgs, expectedArgs, customEqualityTesters); + }, + + wasPrevented: function(selector, eventName) { + var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)], + args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args, + e = args ? args[0] : undefined; + + return e && e.isDefaultPrevented(); + }, + + wasStopped: function(selector, eventName) { + var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)], + args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args, + e = args ? args[0] : undefined; + + return e && e.isPropagationStopped(); + }, + + cleanUp: function() { + data.spiedEvents = {}; + data.handlers = []; + } + }; + /* jshint ignore:end */ +})); diff --git a/common/static/js/libs/jasmine-stealth.js b/common/static/js/libs/jasmine-stealth.js new file mode 100644 index 0000000000..5ec68c04e9 --- /dev/null +++ b/common/static/js/libs/jasmine-stealth.js @@ -0,0 +1,64 @@ +// Custom library to replace the legacy non jasmine 2.0 compatible jasmine-stealth +// jshint ignore: start +(function (root, factory) { + factory(root, root.jasmine, root._); +}((function () { + return this; +}()), function (window, jasmine, _) { + var fake, clearSpies, spyOnConstructor, unfakes = []; + + clearSpies = function () { + _.each(unfakes, function (u) { + return u(); + }); + return unfakes = []; + }; + + fake = function (owner, thingToFake, newThing) { + var originalThing; + originalThing = owner[thingToFake]; + owner[thingToFake] = newThing; + return unfakes.push(function () { + return owner[thingToFake] = originalThing; + }); + }; + + spyOnConstructor = function (owner, classToFake, methodsToSpy) { + var fakeClass, spies; + + fakeClass = (function () { + function _Class() { + spies.constructor.apply(this, arguments); + } + + return _Class; + })(); + + if (!methodsToSpy) { + methodsToSpy = []; + } + + if (_.isString(methodsToSpy)) { + methodsToSpy = [methodsToSpy]; + } + + spies = { + constructor: jasmine.createSpy('' + classToFake + '\'s constructor') + }; + + _.each(methodsToSpy, function (methodName) { + spies[methodName] = jasmine.createSpy('' + classToFake + '#' + methodName); + return fakeClass.prototype[methodName] = function () { + return spies[methodName].apply(this, arguments); + }; + }); + + fake(owner, classToFake, fakeClass); + return spies; + }; + + jasmine.stealth = { + spyOnConstructor: spyOnConstructor, + clearSpies: clearSpies + }; +})); \ No newline at end of file diff --git a/common/static/js/libs/jasmine-waituntil.js b/common/static/js/libs/jasmine-waituntil.js new file mode 100644 index 0000000000..43060c4412 --- /dev/null +++ b/common/static/js/libs/jasmine-waituntil.js @@ -0,0 +1,48 @@ + +// Takes a latch function and optionally timeout and error message. +// Polls the latch function until the it returns true or the maximum timeout expires +// whichever comes first. +(function(root, factory) { + /* jshint strict: false */ + factory(root, root.jQuery); +}((function() { + /* jshint strict: false */ + return this; +}()), function(window, $) { + 'use strict'; + + var MAX_TIMEOUT = jasmine.DEFAULT_TIMEOUT_INTERVAL; + var realSetTimeout = setTimeout; + var realClearTimeout = clearTimeout; + jasmine.waitUntil = function(conditionalFn, maxTimeout, message) { + var deferred = $.Deferred(), + elapsedTimeInMs = 0, + timeout; + + maxTimeout = maxTimeout || MAX_TIMEOUT; + message = message || 'Timeout has expired'; + + var fn = function() { + elapsedTimeInMs += 50; + if (conditionalFn()) { + if (timeout) { realClearTimeout(timeout); } + deferred.resolve(); + } else { + if (elapsedTimeInMs >= maxTimeout) { + // explicitly fail the spec with the given message + fail(message); // jshint ignore:line + + // clear timeout and reject the promise + realClearTimeout(timeout); + deferred.reject(); + + return; + } + timeout = realSetTimeout(fn, 50); + } + }; + + realSetTimeout(fn, 50); + return deferred.promise(); + }; +})); diff --git a/common/static/js/spec/CSS3_workarounds_spec.js b/common/static/js/spec/CSS3_workarounds_spec.js index 107f08f4a4..8b6f746cb6 100644 --- a/common/static/js/spec/CSS3_workarounds_spec.js +++ b/common/static/js/spec/CSS3_workarounds_spec.js @@ -1,4 +1,6 @@ describe("CSS3 workarounds", function() { + 'use strict'; + var pointerEventsNone = window.pointerEventsNone; describe("pointer-events", function() { beforeEach(function() { var html = "What wondrous life in this I lead"; @@ -21,17 +23,7 @@ describe("CSS3 workarounds", function() { }); it("should prevent default when pointerEvents is not Supported", function() { - // mock document.body.style so it does not include 'pointerEvents' - var mockBodyStyle = {}, - bodyStyleKeys = Object.keys(document.body.style); - for (var index = 0; index < bodyStyleKeys.length; index++) { - var key = bodyStyleKeys[index]; - if (key !== "pointerEvents") { - mockBodyStyle[key] = document.body.style[key]; - }; - }; - - pointerEventsNone(".is-disabled", mockBodyStyle); + pointerEventsNone(".is-disabled", {}); spyOnEvent(".is-disabled", "click"); $(".is-disabled").click(); expect("click").toHaveBeenPreventedOn(".is-disabled"); diff --git a/common/static/js/spec/lang_edx_spec.js b/common/static/js/spec/lang_edx_spec.js index 3d8f4f48b9..b335bc1ddb 100644 --- a/common/static/js/spec/lang_edx_spec.js +++ b/common/static/js/spec/lang_edx_spec.js @@ -19,34 +19,34 @@ }); it("should make an AJAX request to the correct URL", function () { - spyOn($, 'ajax').andReturn(deferred); + spyOn($, 'ajax').and.returnValue(deferred); Language.init(); lang_selector.trigger('change'); - expect($.ajax.mostRecentCall.args[0].url).toEqual("/api/user/v1/preferences/test1/"); + expect($.ajax.calls.mostRecent().args[0].url).toEqual("/api/user/v1/preferences/test1/"); }); it("should make an AJAX request with correct type", function () { - spyOn($, 'ajax').andReturn(deferred); + spyOn($, 'ajax').and.returnValue(deferred); Language.init(); lang_selector.trigger('change'); - expect($.ajax.mostRecentCall.args[0].type).toEqual("PATCH"); + expect($.ajax.calls.mostRecent().args[0].type).toEqual("PATCH"); }); it("should make an AJAX request with correct data", function () { - spyOn($, 'ajax').andReturn(deferred); + spyOn($, 'ajax').and.returnValue(deferred); Language.init(); lang_selector.val('ar'); lang_selector.trigger('change'); - expect($.ajax.mostRecentCall.args[0].data).toEqual('{"pref-lang":"ar"}'); + expect($.ajax.calls.mostRecent().args[0].data).toEqual('{"pref-lang":"ar"}'); // change to 'en' from 'ar' lang_selector.val('en'); lang_selector.trigger('change'); - expect($.ajax.mostRecentCall.args[0].data).toEqual('{"pref-lang":"en"}'); + expect($.ajax.calls.mostRecent().args[0].data).toEqual('{"pref-lang":"en"}'); }); it("should call refresh on ajax failure", function () { - spyOn($, 'ajax').andCallFake(function () { + spyOn($, 'ajax').and.callFake(function () { var d = $.Deferred(); d.reject(); return d.promise(); diff --git a/common/static/js/spec/tooltip_manager_spec.js b/common/static/js/spec/tooltip_manager_spec.js index c4011b1f95..e6cd2d2c0e 100644 --- a/common/static/js/spec/tooltip_manager_spec.js +++ b/common/static/js/spec/tooltip_manager_spec.js @@ -11,24 +11,37 @@ describe('TooltipManager', function () { this.element = $('#test-id'); this.tooltip = new TooltipManager(document.body); - jasmine.Clock.useMock(); + jasmine.clock().install(); // Set default dimensions to make testing easer. $('.tooltip').height(HEIGHT).width(WIDTH); // Re-write default jasmine-jquery to consider opacity. - this.addMatchers({ + jasmine.addMatchers({ toBeVisible: function() { - return this.actual.is(':visible') || parseFloat(this.actual.css('opacity')); + return { + compare: function (actual) { + return { + pass: actual.is(':visible') || parseFloat(actual.css('opacity')) + }; + } + }; }, - toBeHidden: function() { - return this.actual.is(':hidden') || !parseFloat(this.actual.css('opacity')); - }, + toBeHidden: function () { + return { + compare: function (actual) { + return { + pass: actual.is(':hidden') || !parseFloat(actual.css('opacity')) + }; + } + }; + } }); }); afterEach(function () { this.tooltip.destroy(); + jasmine.clock().uninstall(); }); showTooltip = function (element) { @@ -36,7 +49,7 @@ describe('TooltipManager', function () { pageX: PAGE_X, pageY: PAGE_Y })); - jasmine.Clock.tick(500); + jasmine.clock().tick(500); }; it('can destroy itself', function () { @@ -58,7 +71,7 @@ describe('TooltipManager', function () { showTooltip(this.element); expect($('.tooltip')).toBeVisible(); this.element.trigger($.Event("mouseout")); - jasmine.Clock.tick(50); + jasmine.clock().tick(50); expect($('.tooltip')).toBeHidden(); }); @@ -66,7 +79,7 @@ describe('TooltipManager', function () { showTooltip(this.element); expect($('.tooltip')).toBeVisible(); this.element.trigger($.Event("click")); - jasmine.Clock.tick(50); + jasmine.clock().tick(50); expect($('.tooltip')).toBeHidden(); }); diff --git a/common/static/js/src/CSS3_workarounds.js b/common/static/js/src/CSS3_workarounds.js index 3608782683..b9c14a1dad 100644 --- a/common/static/js/src/CSS3_workarounds.js +++ b/common/static/js/src/CSS3_workarounds.js @@ -2,7 +2,7 @@ // supported in older browsers var pointerEventsNone = function (selector, supportedStyles) { - // Check to see if the brower supports 'pointer-events' css rule. + // Check to see if the browser supports 'pointer-events' css rule. // If it doesn't, use javascript to stop the link from working // when clicked. $(selector).click(function (event) { diff --git a/common/static/js/vendor/jasmine-imagediff.js b/common/static/js/vendor/jasmine-imagediff.js index 6460e59dc5..230fce0ff8 100644 --- a/common/static/js/vendor/jasmine-imagediff.js +++ b/common/static/js/vendor/jasmine-imagediff.js @@ -268,52 +268,71 @@ return element; } + function imageDiffEqualMessage (actual, expected) { + return function () { + var + div = get('div'), + a = get('div', '