diff --git a/common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee
index 6c8ff116352bee331bbfbc9d071824f55bade986..9e2aab0c258514c8c9c9f9c5f6b00adfeb5b4a38 100644
--- a/common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee
@@ -70,12 +70,12 @@ describe 'Problem', ->
     it 'bind the math input', ->
       expect($('input.math')).toHandleWith 'keyup', @problem.refreshMath
 
-# TODO figure out why this is failing
-#    it 'replace math content on the page', ->
-#      expect(MathJax.Hub.Queue.mostRecentCall.args).toEqual [
-#        ['Text', @stubbedJax, ''],
-#        [@problem.updateMathML, @stubbedJax, $('#input_example_1').get(0)]
-#      ]
+    # TODO: figure out why failing
+    xit 'replace math content on the page', ->
+      expect(MathJax.Hub.Queue.mostRecentCall.args).toEqual [
+        ['Text', @stubbedJax, ''],
+        [@problem.updateMathML, @stubbedJax, $('#input_example_1').get(0)]
+      ]
 
   describe 'render', ->
     beforeEach ->
@@ -138,14 +138,14 @@ describe 'Problem', ->
         @problem.check()
         expect(@problem.el.html()).toEqual 'Incorrect!'
 
-# TODO figure out why this is failing
-#    describe 'when the response is undetermined', ->
-#      it 'alert the response', ->
-#        spyOn window, 'alert'
-#        spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
-#          callback(success: 'Number Only!')
-#        @problem.check()
-#        expect(window.alert).toHaveBeenCalledWith 'Number Only!'
+    # TODO: figure out why failing
+    xdescribe 'when the response is undetermined', ->
+      it 'alert the response', ->
+        spyOn window, 'alert'
+        spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
+          callback(success: 'Number Only!')
+        @problem.check()
+        expect(window.alert).toHaveBeenCalledWith 'Number Only!'
 
   describe 'reset', ->
     beforeEach ->
@@ -264,12 +264,12 @@ describe 'Problem', ->
       expect($.postWithPrefix).toHaveBeenCalledWith '/problem/Problem1/problem_save', 
           'foo=1&bar=2', jasmine.any(Function)
 
-# TODO figure out why this is failing
-#    it 'alert to the user', ->
-#      spyOn window, 'alert'
-#      spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'OK')
-#      @problem.save()
-#      expect(window.alert).toHaveBeenCalledWith 'Saved'
+    # TODO: figure out why failing
+    xit 'alert to the user', ->
+      spyOn window, 'alert'
+      spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback(success: 'OK')
+      @problem.save()
+      expect(window.alert).toHaveBeenCalledWith 'Saved'
 
   describe 'refreshMath', ->
     beforeEach ->
@@ -323,10 +323,10 @@ describe 'Problem', ->
       @problem.refreshAnswers()
       expect(@stubCodeMirror.save).toHaveBeenCalled()
 
-# TODO figure out why this is failing
-#    it 'serialize all answers', ->
-#      @problem.refreshAnswers()
-#      expect(@problem.answers).toEqual "input_1_1=one&input_1_2=two"
+    # TODO: figure out why failing
+    xit 'serialize all answers', ->
+      @problem.refreshAnswers()
+      expect(@problem.answers).toEqual "input_1_1=one&input_1_2=two"
 
 
 
diff --git a/common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee
index 1bf909d75a4c0309468414d8e7571cc3b3967c81..1944f7dc74bafbcbb4e2f68e905325dc21beaa2e 100644
--- a/common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee
@@ -1,159 +1,160 @@
-#describe 'Sequence', ->
-#  beforeEach ->
-#    # Stub MathJax
-#    window.MathJax = { Hub: { Queue: -> } }
-#    spyOn Logger, 'log'
-#
-#    loadFixtures 'sequence.html'
-#    @items = $.parseJSON readFixtures('items.json')
-#
-#  describe 'constructor', ->
-#    beforeEach ->
-#      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 1
-#
-#    it 'set the element', ->
-#      expect(@sequence.el).toEqual $('#sequence_1')
-#
-#    it 'build the navigation', ->
-#      classes = $('#sequence-list li>a').map(-> $(this).attr('class')).get()
-#      elements = $('#sequence-list li>a').map(-> $(this).attr('data-element')).get()
-#      titles = $('#sequence-list li>a>p').map(-> $(this).html()).get()
-#
-#      expect(classes).toEqual ['seq_video_active', 'seq_video_inactive', 'seq_problem_inactive']
-#      expect(elements).toEqual ['1', '2', '3']
-#      expect(titles).toEqual ['Video 1', 'Video 2', 'Sample Problem']
-#
-#    it 'bind the page events', ->
-#      expect($('#sequence-list a')).toHandleWith 'click', @sequence.goto
-#
-#    it 'render the active sequence content', ->
-#      expect($('#seq_content').html()).toEqual 'Video 1'
-#
-#  describe 'toggleArrows', ->
-#    beforeEach ->
-#      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 1
-#
-#    describe 'when the first tab is active', ->
-#      beforeEach ->
-#        @sequence.position = 1
-#        @sequence.toggleArrows()
-#
-#      it 'disable the previous button', ->
-#        expect($('.sequence-nav-buttons .prev a')).toHaveClass 'disabled'
-#
-#      it 'enable the next button', ->
-#        expect($('.sequence-nav-buttons .next a')).not.toHaveClass 'disabled'
-#        expect($('.sequence-nav-buttons .next a')).toHandleWith 'click', @sequence.next
-#
-#    describe 'when the middle tab is active', ->
-#      beforeEach ->
-#        @sequence.position = 2
-#        @sequence.toggleArrows()
-#
-#      it 'enable the previous button', ->
-#        expect($('.sequence-nav-buttons .prev a')).not.toHaveClass 'disabled'
-#        expect($('.sequence-nav-buttons .prev a')).toHandleWith 'click', @sequence.previous
-#
-#      it 'enable the next button', ->
-#        expect($('.sequence-nav-buttons .next a')).not.toHaveClass 'disabled'
-#        expect($('.sequence-nav-buttons .next a')).toHandleWith 'click', @sequence.next
-#
-#    describe 'when the last tab is active', ->
-#      beforeEach ->
-#        @sequence.position = 3
-#        @sequence.toggleArrows()
-#
-#      it 'enable the previous button', ->
-#        expect($('.sequence-nav-buttons .prev a')).not.toHaveClass 'disabled'
-#        expect($('.sequence-nav-buttons .prev a')).toHandleWith 'click', @sequence.previous
-#
-#      it 'disable the next button', ->
-#        expect($('.sequence-nav-buttons .next a')).toHaveClass 'disabled'
-#
-#  describe 'render', ->
-#    beforeEach ->
-#      spyOn $, 'postWithPrefix'
-#      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence'
-#      spyOnEvent @sequence.el, 'contentChanged'
-#      spyOn(@sequence, 'toggleArrows').andCallThrough()
-#
-#    describe 'with a different position than the current one', ->
-#      beforeEach ->
-#        @sequence.render 1
-#
-#      describe 'with no previous position', ->
-#        it 'does not save the new position', ->
-#          expect($.postWithPrefix).not.toHaveBeenCalled()
-#
-#      describe 'with previous position', ->
-#        beforeEach ->
-#          @sequence.position = 2
-#          @sequence.render 1
-#
-#        it 'mark the previous tab as visited', ->
-#          expect($('[data-element="2"]')).toHaveClass 'seq_video_visited'
-#
-#        it 'save the new position', ->
-#          expect($.postWithPrefix).toHaveBeenCalledWith '/modx/1/goto_position', position: 1
-#
-#      it 'mark new tab as active', ->
-#        expect($('[data-element="1"]')).toHaveClass 'seq_video_active'
-#
-#      it 'render the new content', ->
-#        expect($('#seq_content').html()).toEqual 'Video 1'
-#
-#      it 'update the position', ->
-#        expect(@sequence.position).toEqual 1
-#
-#      it 're-update the arrows', ->
-#        expect(@sequence.toggleArrows).toHaveBeenCalled()
-#
-#      it 'trigger contentChanged event', ->
-#        expect('contentChanged').toHaveBeenTriggeredOn @sequence.el
-#
-#    describe 'with the same position as the current one', ->
-#      it 'should not trigger contentChanged event', ->
-#        @sequence.position = 2
-#        @sequence.render 2
-#        expect('contentChanged').not.toHaveBeenTriggeredOn @sequence.el
-#
-#  describe 'goto', ->
-#    beforeEach ->
-#      jasmine.stubRequests()
-#      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
-#      $('[data-element="3"]').click()
-#
-#    it 'log the sequence goto event', ->
-#      expect(Logger.log).toHaveBeenCalledWith 'seq_goto', old: 2, new: 3, id: '1'
-#
-#    it 'call render on the right sequence', ->
-#      expect($('#seq_content').html()).toEqual 'Sample Problem'
-#
-#  describe 'next', ->
-#    beforeEach ->
-#      jasmine.stubRequests()
-#      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
-#      $('.sequence-nav-buttons .next a').click()
-#
-#    it 'log the next sequence event', ->
-#      expect(Logger.log).toHaveBeenCalledWith 'seq_next', old: 2, new: 3, id: '1'
-#
-#    it 'call render on the next sequence', ->
-#      expect($('#seq_content').html()).toEqual 'Sample Problem'
-#
-#  describe 'previous', ->
-#    beforeEach ->
-#      jasmine.stubRequests()
-#      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
-#      $('.sequence-nav-buttons .prev a').click()
-#
-#    it 'log the previous sequence event', ->
-#      expect(Logger.log).toHaveBeenCalledWith 'seq_prev', old: 2, new: 1, id: '1'
-#
-#    it 'call render on the previous sequence', ->
-#      expect($('#seq_content').html()).toEqual 'Video 1'
-#
-#  describe 'link_for', ->
-#    it 'return a link for specific position', ->
-#      sequence = new Sequence '1', 'sequence_1', @items, 2
-#      expect(sequence.link_for(2)).toBe '[data-element="2"]'
+# TODO: figure out why failing
+xdescribe 'Sequence', ->
+  beforeEach ->
+    # Stub MathJax
+    window.MathJax = { Hub: { Queue: -> } }
+    spyOn Logger, 'log'
+
+    loadFixtures 'sequence.html'
+    @items = $.parseJSON readFixtures('items.json')
+
+  describe 'constructor', ->
+    beforeEach ->
+      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 1
+
+    it 'set the element', ->
+      expect(@sequence.el).toEqual $('#sequence_1')
+
+    it 'build the navigation', ->
+      classes = $('#sequence-list li>a').map(-> $(this).attr('class')).get()
+      elements = $('#sequence-list li>a').map(-> $(this).attr('data-element')).get()
+      titles = $('#sequence-list li>a>p').map(-> $(this).html()).get()
+
+      expect(classes).toEqual ['seq_video_active', 'seq_video_inactive', 'seq_problem_inactive']
+      expect(elements).toEqual ['1', '2', '3']
+      expect(titles).toEqual ['Video 1', 'Video 2', 'Sample Problem']
+
+    it 'bind the page events', ->
+      expect($('#sequence-list a')).toHandleWith 'click', @sequence.goto
+
+    it 'render the active sequence content', ->
+      expect($('#seq_content').html()).toEqual 'Video 1'
+
+  describe 'toggleArrows', ->
+    beforeEach ->
+      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 1
+
+    describe 'when the first tab is active', ->
+      beforeEach ->
+        @sequence.position = 1
+        @sequence.toggleArrows()
+
+      it 'disable the previous button', ->
+        expect($('.sequence-nav-buttons .prev a')).toHaveClass 'disabled'
+
+      it 'enable the next button', ->
+        expect($('.sequence-nav-buttons .next a')).not.toHaveClass 'disabled'
+        expect($('.sequence-nav-buttons .next a')).toHandleWith 'click', @sequence.next
+
+    describe 'when the middle tab is active', ->
+      beforeEach ->
+        @sequence.position = 2
+        @sequence.toggleArrows()
+
+      it 'enable the previous button', ->
+        expect($('.sequence-nav-buttons .prev a')).not.toHaveClass 'disabled'
+        expect($('.sequence-nav-buttons .prev a')).toHandleWith 'click', @sequence.previous
+
+      it 'enable the next button', ->
+        expect($('.sequence-nav-buttons .next a')).not.toHaveClass 'disabled'
+        expect($('.sequence-nav-buttons .next a')).toHandleWith 'click', @sequence.next
+
+    describe 'when the last tab is active', ->
+      beforeEach ->
+        @sequence.position = 3
+        @sequence.toggleArrows()
+
+      it 'enable the previous button', ->
+        expect($('.sequence-nav-buttons .prev a')).not.toHaveClass 'disabled'
+        expect($('.sequence-nav-buttons .prev a')).toHandleWith 'click', @sequence.previous
+
+      it 'disable the next button', ->
+        expect($('.sequence-nav-buttons .next a')).toHaveClass 'disabled'
+
+  describe 'render', ->
+    beforeEach ->
+      spyOn $, 'postWithPrefix'
+      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence'
+      spyOnEvent @sequence.el, 'contentChanged'
+      spyOn(@sequence, 'toggleArrows').andCallThrough()
+
+    describe 'with a different position than the current one', ->
+      beforeEach ->
+        @sequence.render 1
+
+      describe 'with no previous position', ->
+        it 'does not save the new position', ->
+          expect($.postWithPrefix).not.toHaveBeenCalled()
+
+      describe 'with previous position', ->
+        beforeEach ->
+          @sequence.position = 2
+          @sequence.render 1
+
+        it 'mark the previous tab as visited', ->
+          expect($('[data-element="2"]')).toHaveClass 'seq_video_visited'
+
+        it 'save the new position', ->
+          expect($.postWithPrefix).toHaveBeenCalledWith '/modx/1/goto_position', position: 1
+
+      it 'mark new tab as active', ->
+        expect($('[data-element="1"]')).toHaveClass 'seq_video_active'
+
+      it 'render the new content', ->
+        expect($('#seq_content').html()).toEqual 'Video 1'
+
+      it 'update the position', ->
+        expect(@sequence.position).toEqual 1
+
+      it 're-update the arrows', ->
+        expect(@sequence.toggleArrows).toHaveBeenCalled()
+
+      it 'trigger contentChanged event', ->
+        expect('contentChanged').toHaveBeenTriggeredOn @sequence.el
+
+    describe 'with the same position as the current one', ->
+      it 'should not trigger contentChanged event', ->
+        @sequence.position = 2
+        @sequence.render 2
+        expect('contentChanged').not.toHaveBeenTriggeredOn @sequence.el
+
+  describe 'goto', ->
+    beforeEach ->
+      jasmine.stubRequests()
+      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
+      $('[data-element="3"]').click()
+
+    it 'log the sequence goto event', ->
+      expect(Logger.log).toHaveBeenCalledWith 'seq_goto', old: 2, new: 3, id: '1'
+
+    it 'call render on the right sequence', ->
+      expect($('#seq_content').html()).toEqual 'Sample Problem'
+
+  describe 'next', ->
+    beforeEach ->
+      jasmine.stubRequests()
+      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
+      $('.sequence-nav-buttons .next a').click()
+
+    it 'log the next sequence event', ->
+      expect(Logger.log).toHaveBeenCalledWith 'seq_next', old: 2, new: 3, id: '1'
+
+    it 'call render on the next sequence', ->
+      expect($('#seq_content').html()).toEqual 'Sample Problem'
+
+  describe 'previous', ->
+    beforeEach ->
+      jasmine.stubRequests()
+      @sequence = new Sequence '1', 'sequence_1', @items, 'sequence', 2
+      $('.sequence-nav-buttons .prev a').click()
+
+    it 'log the previous sequence event', ->
+      expect(Logger.log).toHaveBeenCalledWith 'seq_prev', old: 2, new: 1, id: '1'
+
+    it 'call render on the previous sequence', ->
+      expect($('#seq_content').html()).toEqual 'Video 1'
+
+  describe 'link_for', ->
+    it 'return a link for specific position', ->
+      sequence = new Sequence '1', 'sequence_1', @items, 2
+      expect(sequence.link_for(2)).toBe '[data-element="2"]'
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
index 9dcb705239b53efa51df478ca06aee4aac2cc699..90e026e57e0178b1ec7d15d74808cf781736c25b 100644
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
@@ -1,337 +1,338 @@
-#describe 'VideoCaption', ->
-#  beforeEach ->
-#    jasmine.stubVideoPlayer @
-#    $('.subtitles').remove()
-#
-#  afterEach ->
-#    YT.Player = undefined
-#    $.fn.scrollTo.reset()
-#
-#  describe 'constructor', ->
-#    beforeEach ->
-#      spyOn($, 'getWithPrefix').andCallThrough()
-#
-#    describe 'always', ->
-#      beforeEach ->
-#        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#
-#      it 'set the youtube id', ->
-#        expect(@caption.youtubeId).toEqual 'def456'
-#
-#      it 'create the caption element', ->
-#        expect($('.video')).toContain 'ol.subtitles'
-#
-#      it 'add caption control to video player', ->
-#        expect($('.video')).toContain 'a.hide-subtitles'
-#
-#      it 'fetch the caption', ->
-#        expect($.getWithPrefix).toHaveBeenCalledWith @caption.captionURL(), jasmine.any(Function)
-#
-#      it 'bind window resize event', ->
-#        expect($(window)).toHandleWith 'resize', @caption.resize
-#
-#      it 'bind the hide caption button', ->
-#        expect($('.hide-subtitles')).toHandleWith 'click', @caption.toggle
-#
-#      it 'bind the mouse movement', ->
-#        expect($('.subtitles')).toHandleWith 'mouseover', @caption.onMouseEnter
-#        expect($('.subtitles')).toHandleWith 'mouseout', @caption.onMouseLeave
-#        expect($('.subtitles')).toHandleWith 'mousemove', @caption.onMovement
-#        expect($('.subtitles')).toHandleWith 'mousewheel', @caption.onMovement
-#        expect($('.subtitles')).toHandleWith 'DOMMouseScroll', @caption.onMovement
-#
-#    describe 'when on a non touch-based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn false
-#        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#
-#      it 'render the caption', ->
-#        expect($('.subtitles').html()).toMatch new RegExp('''
-#          <li data-index="0" data-start="0">Caption at 0</li>
-#          <li data-index="1" data-start="10000">Caption at 10000</li>
-#          <li data-index="2" data-start="20000">Caption at 20000</li>
-#          <li data-index="3" data-start="30000">Caption at 30000</li>
-#        '''.replace(/\n/g, ''))
-#
-#      it 'add a padding element to caption', ->
-#        expect($('.subtitles li:first')).toBe '.spacing'
-#        expect($('.subtitles li:last')).toBe '.spacing'
-#
-#      it 'bind all the caption link', ->
-#        $('.subtitles li[data-index]').each (index, link) =>
-#          expect($(link)).toHandleWith 'click', @caption.seekPlayer
-#
-#      it 'set rendered to true', ->
-#        expect(@caption.rendered).toBeTruthy()
-#
-#    describe 'when on a touch-based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn true
-#        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#
-#      it 'show explaination message', ->
-#        expect($('.subtitles li')).toHaveHtml "Caption will be displayed when you start playing the video."
-#
-#      it 'does not set rendered to true', ->
-#        expect(@caption.rendered).toBeFalsy()
-#
-#  describe 'mouse movement', ->
-#    beforeEach ->
-#      spyOn(window, 'setTimeout').andReturn 100
-#      spyOn window, 'clearTimeout'
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#
-#    describe 'when cursor is outside of the caption box', ->
-#      beforeEach ->
-#        $(window).trigger jQuery.Event 'mousemove'
-#
-#      it 'does not set freezing timeout', ->
-#        expect(@caption.frozen).toBeFalsy()
-#
-#    describe 'when cursor is in the caption box', ->
-#      beforeEach ->
-#        $('.subtitles').trigger jQuery.Event 'mouseenter'
-#
-#      it 'set the freezing timeout', ->
-#        expect(@caption.frozen).toEqual 100
-#
-#      describe 'when the cursor is moving', ->
-#        beforeEach ->
-#          $('.subtitles').trigger jQuery.Event 'mousemove'
-#
-#        it 'reset the freezing timeout', ->
-#          expect(window.clearTimeout).toHaveBeenCalledWith 100
-#
-#      describe 'when the mouse is scrolling', ->
-#        beforeEach ->
-#          $('.subtitles').trigger jQuery.Event 'mousewheel'
-#
-#        it 'reset the freezing timeout', ->
-#          expect(window.clearTimeout).toHaveBeenCalledWith 100
-#
-#    describe 'when cursor is moving out of the caption box', ->
-#      beforeEach ->
-#        @caption.frozen = 100
-#        $.fn.scrollTo.reset()
-#
-#      describe 'always', ->
-#        beforeEach ->
-#          $('.subtitles').trigger jQuery.Event 'mouseout'
-#
-#        it 'reset the freezing timeout', ->
-#          expect(window.clearTimeout).toHaveBeenCalledWith 100
-#
-#        it 'unfreeze the caption', ->
-#          expect(@caption.frozen).toBeNull()
-#
-#      describe 'when the player is playing', ->
-#        beforeEach ->
-#          @caption.playing = true
-#          $('.subtitles li[data-index]:first').addClass 'current'
-#          $('.subtitles').trigger jQuery.Event 'mouseout'
-#
-#        it 'scroll the caption', ->
-#          expect($.fn.scrollTo).toHaveBeenCalled()
-#
-#      describe 'when the player is not playing', ->
-#        beforeEach ->
-#          @caption.playing = false
-#          $('.subtitles').trigger jQuery.Event 'mouseout'
-#
-#        it 'does not scroll the caption', ->
-#          expect($.fn.scrollTo).not.toHaveBeenCalled()
-#
-#  describe 'search', ->
-#    beforeEach ->
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#
-#    it 'return a correct caption index', ->
-#      expect(@caption.search(0)).toEqual 0
-#      expect(@caption.search(9999)).toEqual 0
-#      expect(@caption.search(10000)).toEqual 1
-#      expect(@caption.search(15000)).toEqual 1
-#      expect(@caption.search(30000)).toEqual 3
-#      expect(@caption.search(30001)).toEqual 3
-#
-#  describe 'play', ->
-#    describe 'when the caption was not rendered', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn true
-#        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#        @caption.play()
-#
-#      it 'render the caption', ->
-#        expect($('.subtitles').html()).toMatch new RegExp(
-#          '''<li data-index="0" data-start="0">Caption at 0</li>''' +
-#          '''<li data-index="1" data-start="10000">Caption at 10000</li>''' +
-#          '''<li data-index="2" data-start="20000">Caption at 20000</li>''' +
-#          '''<li data-index="3" data-start="30000">Caption at 30000</li>'''
-#        )
-#
-#      it 'add a padding element to caption', ->
-#        expect($('.subtitles li:first')).toBe '.spacing'
-#        expect($('.subtitles li:last')).toBe '.spacing'
-#
-#      it 'bind all the caption link', ->
-#        $('.subtitles li[data-index]').each (index, link) =>
-#          expect($(link)).toHandleWith 'click', @caption.seekPlayer
-#
-#      it 'set rendered to true', ->
-#        expect(@caption.rendered).toBeTruthy()
-#
-#      it 'set playing to true', ->
-#        expect(@caption.playing).toBeTruthy()
-#
-#  describe 'pause', ->
-#    beforeEach ->
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#      @caption.playing = true
-#      @caption.pause()
-#
-#    it 'set playing to false', ->
-#      expect(@caption.playing).toBeFalsy()
-#
-#  describe 'updatePlayTime', ->
-#    beforeEach ->
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#
-#    describe 'when the video speed is 1.0x', ->
-#      beforeEach ->
-#        @caption.currentSpeed = '1.0'
-#        @caption.updatePlayTime 25.000
-#
-#      it 'search the caption based on time', ->
-#        expect(@caption.currentIndex).toEqual 2
-#
-#    describe 'when the video speed is not 1.0x', ->
-#      beforeEach ->
-#        @caption.currentSpeed = '0.75'
-#        @caption.updatePlayTime 25.000
-#
-#      it 'search the caption based on 1.0x speed', ->
-#        expect(@caption.currentIndex).toEqual 1
-#
-#    describe 'when the index is not the same', ->
-#      beforeEach ->
-#        @caption.currentIndex = 1
-#        $('.subtitles li[data-index=1]').addClass 'current'
-#        @caption.updatePlayTime 25.000
-#
-#      it 'deactivate the previous caption', ->
-#        expect($('.subtitles li[data-index=1]')).not.toHaveClass 'current'
-#
-#      it 'activate new caption', ->
-#        expect($('.subtitles li[data-index=2]')).toHaveClass 'current'
-#
-#      it 'save new index', ->
-#        expect(@caption.currentIndex).toEqual 2
-#
-#      it 'scroll caption to new position', ->
-#        expect($.fn.scrollTo).toHaveBeenCalled()
-#
-#    describe 'when the index is the same', ->
-#      beforeEach ->
-#        @caption.currentIndex = 1
-#        $('.subtitles li[data-index=1]').addClass 'current'
-#        @caption.updatePlayTime 15.000
-#
-#      it 'does not change current subtitle', ->
-#        expect($('.subtitles li[data-index=1]')).toHaveClass 'current'
-#
-#  describe 'resize', ->
-#    beforeEach ->
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#      $('.subtitles li[data-index=1]').addClass 'current'
-#      @caption.resize()
-#
-#    it 'set the height of caption container', ->
-#      expect(parseInt($('.subtitles').css('maxHeight'))).toEqual $('.video-wrapper').height()
-#
-#    it 'set the height of caption spacing', ->
-#      expect(parseInt($('.subtitles .spacing:first').css('height'))).toEqual(
-#        $('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):first').height() / 2)
-#      expect(parseInt($('.subtitles .spacing:last').css('height'))).toEqual(
-#        $('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):last').height() / 2)
-#
-#    it 'scroll caption to new position', ->
-#      expect($.fn.scrollTo).toHaveBeenCalled()
-#
-#  describe 'scrollCaption', ->
-#    beforeEach ->
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#
-#    describe 'when frozen', ->
-#      beforeEach ->
-#        @caption.frozen = true
-#        $('.subtitles li[data-index=1]').addClass 'current'
-#        @caption.scrollCaption()
-#
-#      it 'does not scroll the caption', ->
-#        expect($.fn.scrollTo).not.toHaveBeenCalled()
-#
-#    describe 'when not frozen', ->
-#      beforeEach ->
-#        @caption.frozen = false
-#
-#      describe 'when there is no current caption', ->
-#        beforeEach ->
-#          @caption.scrollCaption()
-#
-#        it 'does not scroll the caption', ->
-#          expect($.fn.scrollTo).not.toHaveBeenCalled()
-#
-#      describe 'when there is a current caption', ->
-#        beforeEach ->
-#          $('.subtitles li[data-index=1]').addClass 'current'
-#          @caption.scrollCaption()
-#
-#        it 'scroll to current caption', ->
-#          expect($.fn.scrollTo).toHaveBeenCalledWith $('.subtitles .current:first', @caption.el),
-#            offset: - ($('.video-wrapper').height() / 2 - $('.subtitles .current:first').height() / 2)
-#
-#  describe 'seekPlayer', ->
-#    beforeEach ->
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#      @time = null
-#      $(@caption).bind 'seek', (event, time) => @time = time
-#
-#    describe 'when the video speed is 1.0x', ->
-#      beforeEach ->
-#        @caption.currentSpeed = '1.0'
-#        $('.subtitles li[data-start="30000"]').click()
-#
-#      it 'trigger seek event with the correct time', ->
-#        expect(@time).toEqual 30.000
-#
-#    describe 'when the video speed is not 1.0x', ->
-#      beforeEach ->
-#        @caption.currentSpeed = '0.75'
-#        $('.subtitles li[data-start="30000"]').click()
-#
-#      it 'trigger seek event with the correct time', ->
-#        expect(@time).toEqual 40.000
-#
-#  describe 'toggle', ->
-#    beforeEach ->
-#      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
-#      $('.subtitles li[data-index=1]').addClass 'current'
-#
-#    describe 'when the caption is visible', ->
-#      beforeEach ->
-#        @caption.el.removeClass 'closed'
-#        @caption.toggle jQuery.Event('click')
-#
-#      it 'hide the caption', ->
-#        expect(@caption.el).toHaveClass 'closed'
-#
-#
-#    describe 'when the caption is hidden', ->
-#      beforeEach ->
-#        @caption.el.addClass 'closed'
-#        @caption.toggle jQuery.Event('click')
-#
-#      it 'show the caption', ->
-#        expect(@caption.el).not.toHaveClass 'closed'
-#
-#      it 'scroll the caption', ->
-#        expect($.fn.scrollTo).toHaveBeenCalled()
+# TODO: figure out why failing
+xdescribe 'VideoCaption', ->
+  beforeEach ->
+    jasmine.stubVideoPlayer @
+    $('.subtitles').remove()
+
+  afterEach ->
+    YT.Player = undefined
+    $.fn.scrollTo.reset()
+
+  describe 'constructor', ->
+    beforeEach ->
+      spyOn($, 'getWithPrefix').andCallThrough()
+
+    describe 'always', ->
+      beforeEach ->
+        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+
+      it 'set the youtube id', ->
+        expect(@caption.youtubeId).toEqual 'def456'
+
+      it 'create the caption element', ->
+        expect($('.video')).toContain 'ol.subtitles'
+
+      it 'add caption control to video player', ->
+        expect($('.video')).toContain 'a.hide-subtitles'
+
+      it 'fetch the caption', ->
+        expect($.getWithPrefix).toHaveBeenCalledWith @caption.captionURL(), jasmine.any(Function)
+
+      it 'bind window resize event', ->
+        expect($(window)).toHandleWith 'resize', @caption.resize
+
+      it 'bind the hide caption button', ->
+        expect($('.hide-subtitles')).toHandleWith 'click', @caption.toggle
+
+      it 'bind the mouse movement', ->
+        expect($('.subtitles')).toHandleWith 'mouseover', @caption.onMouseEnter
+        expect($('.subtitles')).toHandleWith 'mouseout', @caption.onMouseLeave
+        expect($('.subtitles')).toHandleWith 'mousemove', @caption.onMovement
+        expect($('.subtitles')).toHandleWith 'mousewheel', @caption.onMovement
+        expect($('.subtitles')).toHandleWith 'DOMMouseScroll', @caption.onMovement
+
+    describe 'when on a non touch-based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn false
+        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+
+      it 'render the caption', ->
+        expect($('.subtitles').html()).toMatch new RegExp('''
+          <li data-index="0" data-start="0">Caption at 0</li>
+          <li data-index="1" data-start="10000">Caption at 10000</li>
+          <li data-index="2" data-start="20000">Caption at 20000</li>
+          <li data-index="3" data-start="30000">Caption at 30000</li>
+        '''.replace(/\n/g, ''))
+
+      it 'add a padding element to caption', ->
+        expect($('.subtitles li:first')).toBe '.spacing'
+        expect($('.subtitles li:last')).toBe '.spacing'
+
+      it 'bind all the caption link', ->
+        $('.subtitles li[data-index]').each (index, link) =>
+          expect($(link)).toHandleWith 'click', @caption.seekPlayer
+
+      it 'set rendered to true', ->
+        expect(@caption.rendered).toBeTruthy()
+
+    describe 'when on a touch-based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn true
+        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+
+      it 'show explaination message', ->
+        expect($('.subtitles li')).toHaveHtml "Caption will be displayed when you start playing the video."
+
+      it 'does not set rendered to true', ->
+        expect(@caption.rendered).toBeFalsy()
+
+  describe 'mouse movement', ->
+    beforeEach ->
+      spyOn(window, 'setTimeout').andReturn 100
+      spyOn window, 'clearTimeout'
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+
+    describe 'when cursor is outside of the caption box', ->
+      beforeEach ->
+        $(window).trigger jQuery.Event 'mousemove'
+
+      it 'does not set freezing timeout', ->
+        expect(@caption.frozen).toBeFalsy()
+
+    describe 'when cursor is in the caption box', ->
+      beforeEach ->
+        $('.subtitles').trigger jQuery.Event 'mouseenter'
+
+      it 'set the freezing timeout', ->
+        expect(@caption.frozen).toEqual 100
+
+      describe 'when the cursor is moving', ->
+        beforeEach ->
+          $('.subtitles').trigger jQuery.Event 'mousemove'
+
+        it 'reset the freezing timeout', ->
+          expect(window.clearTimeout).toHaveBeenCalledWith 100
+
+      describe 'when the mouse is scrolling', ->
+        beforeEach ->
+          $('.subtitles').trigger jQuery.Event 'mousewheel'
+
+        it 'reset the freezing timeout', ->
+          expect(window.clearTimeout).toHaveBeenCalledWith 100
+
+    describe 'when cursor is moving out of the caption box', ->
+      beforeEach ->
+        @caption.frozen = 100
+        $.fn.scrollTo.reset()
+
+      describe 'always', ->
+        beforeEach ->
+          $('.subtitles').trigger jQuery.Event 'mouseout'
+
+        it 'reset the freezing timeout', ->
+          expect(window.clearTimeout).toHaveBeenCalledWith 100
+
+        it 'unfreeze the caption', ->
+          expect(@caption.frozen).toBeNull()
+
+      describe 'when the player is playing', ->
+        beforeEach ->
+          @caption.playing = true
+          $('.subtitles li[data-index]:first').addClass 'current'
+          $('.subtitles').trigger jQuery.Event 'mouseout'
+
+        it 'scroll the caption', ->
+          expect($.fn.scrollTo).toHaveBeenCalled()
+
+      describe 'when the player is not playing', ->
+        beforeEach ->
+          @caption.playing = false
+          $('.subtitles').trigger jQuery.Event 'mouseout'
+
+        it 'does not scroll the caption', ->
+          expect($.fn.scrollTo).not.toHaveBeenCalled()
+
+  describe 'search', ->
+    beforeEach ->
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+
+    it 'return a correct caption index', ->
+      expect(@caption.search(0)).toEqual 0
+      expect(@caption.search(9999)).toEqual 0
+      expect(@caption.search(10000)).toEqual 1
+      expect(@caption.search(15000)).toEqual 1
+      expect(@caption.search(30000)).toEqual 3
+      expect(@caption.search(30001)).toEqual 3
+
+  describe 'play', ->
+    describe 'when the caption was not rendered', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn true
+        @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+        @caption.play()
+
+      it 'render the caption', ->
+        expect($('.subtitles').html()).toMatch new RegExp(
+          '''<li data-index="0" data-start="0">Caption at 0</li>''' +
+          '''<li data-index="1" data-start="10000">Caption at 10000</li>''' +
+          '''<li data-index="2" data-start="20000">Caption at 20000</li>''' +
+          '''<li data-index="3" data-start="30000">Caption at 30000</li>'''
+        )
+
+      it 'add a padding element to caption', ->
+        expect($('.subtitles li:first')).toBe '.spacing'
+        expect($('.subtitles li:last')).toBe '.spacing'
+
+      it 'bind all the caption link', ->
+        $('.subtitles li[data-index]').each (index, link) =>
+          expect($(link)).toHandleWith 'click', @caption.seekPlayer
+
+      it 'set rendered to true', ->
+        expect(@caption.rendered).toBeTruthy()
+
+      it 'set playing to true', ->
+        expect(@caption.playing).toBeTruthy()
+
+  describe 'pause', ->
+    beforeEach ->
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+      @caption.playing = true
+      @caption.pause()
+
+    it 'set playing to false', ->
+      expect(@caption.playing).toBeFalsy()
+
+  describe 'updatePlayTime', ->
+    beforeEach ->
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+
+    describe 'when the video speed is 1.0x', ->
+      beforeEach ->
+        @caption.currentSpeed = '1.0'
+        @caption.updatePlayTime 25.000
+
+      it 'search the caption based on time', ->
+        expect(@caption.currentIndex).toEqual 2
+
+    describe 'when the video speed is not 1.0x', ->
+      beforeEach ->
+        @caption.currentSpeed = '0.75'
+        @caption.updatePlayTime 25.000
+
+      it 'search the caption based on 1.0x speed', ->
+        expect(@caption.currentIndex).toEqual 1
+
+    describe 'when the index is not the same', ->
+      beforeEach ->
+        @caption.currentIndex = 1
+        $('.subtitles li[data-index=1]').addClass 'current'
+        @caption.updatePlayTime 25.000
+
+      it 'deactivate the previous caption', ->
+        expect($('.subtitles li[data-index=1]')).not.toHaveClass 'current'
+
+      it 'activate new caption', ->
+        expect($('.subtitles li[data-index=2]')).toHaveClass 'current'
+
+      it 'save new index', ->
+        expect(@caption.currentIndex).toEqual 2
+
+      it 'scroll caption to new position', ->
+        expect($.fn.scrollTo).toHaveBeenCalled()
+
+    describe 'when the index is the same', ->
+      beforeEach ->
+        @caption.currentIndex = 1
+        $('.subtitles li[data-index=1]').addClass 'current'
+        @caption.updatePlayTime 15.000
+
+      it 'does not change current subtitle', ->
+        expect($('.subtitles li[data-index=1]')).toHaveClass 'current'
+
+  describe 'resize', ->
+    beforeEach ->
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+      $('.subtitles li[data-index=1]').addClass 'current'
+      @caption.resize()
+
+    it 'set the height of caption container', ->
+      expect(parseInt($('.subtitles').css('maxHeight'))).toEqual $('.video-wrapper').height()
+
+    it 'set the height of caption spacing', ->
+      expect(parseInt($('.subtitles .spacing:first').css('height'))).toEqual(
+        $('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):first').height() / 2)
+      expect(parseInt($('.subtitles .spacing:last').css('height'))).toEqual(
+        $('.video-wrapper').height() / 2 - $('.subtitles li:not(.spacing):last').height() / 2)
+
+    it 'scroll caption to new position', ->
+      expect($.fn.scrollTo).toHaveBeenCalled()
+
+  describe 'scrollCaption', ->
+    beforeEach ->
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+
+    describe 'when frozen', ->
+      beforeEach ->
+        @caption.frozen = true
+        $('.subtitles li[data-index=1]').addClass 'current'
+        @caption.scrollCaption()
+
+      it 'does not scroll the caption', ->
+        expect($.fn.scrollTo).not.toHaveBeenCalled()
+
+    describe 'when not frozen', ->
+      beforeEach ->
+        @caption.frozen = false
+
+      describe 'when there is no current caption', ->
+        beforeEach ->
+          @caption.scrollCaption()
+
+        it 'does not scroll the caption', ->
+          expect($.fn.scrollTo).not.toHaveBeenCalled()
+
+      describe 'when there is a current caption', ->
+        beforeEach ->
+          $('.subtitles li[data-index=1]').addClass 'current'
+          @caption.scrollCaption()
+
+        it 'scroll to current caption', ->
+          expect($.fn.scrollTo).toHaveBeenCalledWith $('.subtitles .current:first', @caption.el),
+            offset: - ($('.video-wrapper').height() / 2 - $('.subtitles .current:first').height() / 2)
+
+  describe 'seekPlayer', ->
+    beforeEach ->
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+      @time = null
+      $(@caption).bind 'seek', (event, time) => @time = time
+
+    describe 'when the video speed is 1.0x', ->
+      beforeEach ->
+        @caption.currentSpeed = '1.0'
+        $('.subtitles li[data-start="30000"]').click()
+
+      it 'trigger seek event with the correct time', ->
+        expect(@time).toEqual 30.000
+
+    describe 'when the video speed is not 1.0x', ->
+      beforeEach ->
+        @caption.currentSpeed = '0.75'
+        $('.subtitles li[data-start="30000"]').click()
+
+      it 'trigger seek event with the correct time', ->
+        expect(@time).toEqual 40.000
+
+  describe 'toggle', ->
+    beforeEach ->
+      @caption = new VideoCaption el: $('.video'), youtubeId: 'def456', currentSpeed: '1.0'
+      $('.subtitles li[data-index=1]').addClass 'current'
+
+    describe 'when the caption is visible', ->
+      beforeEach ->
+        @caption.el.removeClass 'closed'
+        @caption.toggle jQuery.Event('click')
+
+      it 'hide the caption', ->
+        expect(@caption.el).toHaveClass 'closed'
+
+
+    describe 'when the caption is hidden', ->
+      beforeEach ->
+        @caption.el.addClass 'closed'
+        @caption.toggle jQuery.Event('click')
+
+      it 'show the caption', ->
+        expect(@caption.el).not.toHaveClass 'closed'
+
+      it 'scroll the caption', ->
+        expect($.fn.scrollTo).toHaveBeenCalled()
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
index 4a780812171bb6944e15937aa561691a6b5ba69e..7603d5777f06909ee6b88bfff4c573c49bcfb1b0 100644
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
@@ -1,109 +1,110 @@
-#describe 'VideoControl', ->
-#  beforeEach ->
-#    jasmine.stubVideoPlayer @
-#    $('.video-controls').html ''
-#
-#  describe 'constructor', ->
-#    it 'render the video controls', ->
-#      new VideoControl(el: $('.video-controls'))
-#      expect($('.video-controls').html()).toContain '''
-#        <div class="slider"></div>
-#        <div>
-#          <ul class="vcr">
-#            <li><a class="video_control play" href="#">Play</a></li>
-#            <li>
-#              <div class="vidtime">0:00 / 0:00</div>
-#            </li>
-#          </ul>
-#          <div class="secondary-controls">
-#            <a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>
-#          </div>
-#        </div>
-#      '''
-#
-#    it 'bind the playback button', ->
-#      control = new VideoControl(el: $('.video-controls'))
-#      expect($('.video_control')).toHandleWith 'click', control.togglePlayback
-#
-#    describe 'when on a touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn true
-#
-#      it 'does not add the play class to video control', ->
-#        new VideoControl(el: $('.video-controls'))
-#        expect($('.video_control')).not.toHaveClass 'play'
-#        expect($('.video_control')).not.toHaveHtml 'Play'
-#
-#
-#    describe 'when on a non-touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn false
-#
-#      it 'add the play class to video control', ->
-#        new VideoControl(el: $('.video-controls'))
-#        expect($('.video_control')).toHaveClass 'play'
-#        expect($('.video_control')).toHaveHtml 'Play'
-#
-#  describe 'play', ->
-#    beforeEach ->
-#      @control = new VideoControl(el: $('.video-controls'))
-#      @control.play()
-#
-#    it 'switch playback button to play state', ->
-#      expect($('.video_control')).not.toHaveClass 'play'
-#      expect($('.video_control')).toHaveClass 'pause'
-#      expect($('.video_control')).toHaveHtml 'Pause'
-#
-#  describe 'pause', ->
-#    beforeEach ->
-#      @control = new VideoControl(el: $('.video-controls'))
-#      @control.pause()
-#
-#    it 'switch playback button to pause state', ->
-#      expect($('.video_control')).not.toHaveClass 'pause'
-#      expect($('.video_control')).toHaveClass 'play'
-#      expect($('.video_control')).toHaveHtml 'Play'
-#
-#  describe 'togglePlayback', ->
-#    beforeEach ->
-#      @control = new VideoControl(el: $('.video-controls'))
-#
-#    describe 'when the control does not have play or pause class', ->
-#      beforeEach ->
-#        $('.video_control').removeClass('play').removeClass('pause')
-#
-#      describe 'when the video is playing', ->
-#        beforeEach ->
-#          $('.video_control').addClass('play')
-#          spyOnEvent @control, 'pause'
-#          @control.togglePlayback jQuery.Event('click')
-#
-#        it 'does not trigger the pause event', ->
-#          expect('pause').not.toHaveBeenTriggeredOn @control
-#
-#      describe 'when the video is paused', ->
-#        beforeEach ->
-#          $('.video_control').addClass('pause')
-#          spyOnEvent @control, 'play'
-#          @control.togglePlayback jQuery.Event('click')
-#
-#        it 'does not trigger the play event', ->
-#          expect('play').not.toHaveBeenTriggeredOn @control
-#
-#      describe 'when the video is playing', ->
-#        beforeEach ->
-#          spyOnEvent @control, 'pause'
-#          $('.video_control').addClass 'pause'
-#          @control.togglePlayback jQuery.Event('click')
-#
-#        it 'trigger the pause event', ->
-#          expect('pause').toHaveBeenTriggeredOn @control
-#
-#      describe 'when the video is paused', ->
-#        beforeEach ->
-#          spyOnEvent @control, 'play'
-#          $('.video_control').addClass 'play'
-#          @control.togglePlayback jQuery.Event('click')
-#
-#        it 'trigger the play event', ->
-#          expect('play').toHaveBeenTriggeredOn @control
+# TODO: figure out why failing
+xdescribe 'VideoControl', ->
+  beforeEach ->
+    jasmine.stubVideoPlayer @
+    $('.video-controls').html ''
+
+  describe 'constructor', ->
+    it 'render the video controls', ->
+      new VideoControl(el: $('.video-controls'))
+      expect($('.video-controls').html()).toContain '''
+        <div class="slider"></div>
+        <div>
+          <ul class="vcr">
+            <li><a class="video_control play" href="#">Play</a></li>
+            <li>
+              <div class="vidtime">0:00 / 0:00</div>
+            </li>
+          </ul>
+          <div class="secondary-controls">
+            <a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>
+          </div>
+        </div>
+      '''
+
+    it 'bind the playback button', ->
+      control = new VideoControl(el: $('.video-controls'))
+      expect($('.video_control')).toHandleWith 'click', control.togglePlayback
+
+    describe 'when on a touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn true
+
+      it 'does not add the play class to video control', ->
+        new VideoControl(el: $('.video-controls'))
+        expect($('.video_control')).not.toHaveClass 'play'
+        expect($('.video_control')).not.toHaveHtml 'Play'
+
+
+    describe 'when on a non-touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn false
+
+      it 'add the play class to video control', ->
+        new VideoControl(el: $('.video-controls'))
+        expect($('.video_control')).toHaveClass 'play'
+        expect($('.video_control')).toHaveHtml 'Play'
+
+  describe 'play', ->
+    beforeEach ->
+      @control = new VideoControl(el: $('.video-controls'))
+      @control.play()
+
+    it 'switch playback button to play state', ->
+      expect($('.video_control')).not.toHaveClass 'play'
+      expect($('.video_control')).toHaveClass 'pause'
+      expect($('.video_control')).toHaveHtml 'Pause'
+
+  describe 'pause', ->
+    beforeEach ->
+      @control = new VideoControl(el: $('.video-controls'))
+      @control.pause()
+
+    it 'switch playback button to pause state', ->
+      expect($('.video_control')).not.toHaveClass 'pause'
+      expect($('.video_control')).toHaveClass 'play'
+      expect($('.video_control')).toHaveHtml 'Play'
+
+  describe 'togglePlayback', ->
+    beforeEach ->
+      @control = new VideoControl(el: $('.video-controls'))
+
+    describe 'when the control does not have play or pause class', ->
+      beforeEach ->
+        $('.video_control').removeClass('play').removeClass('pause')
+
+      describe 'when the video is playing', ->
+        beforeEach ->
+          $('.video_control').addClass('play')
+          spyOnEvent @control, 'pause'
+          @control.togglePlayback jQuery.Event('click')
+
+        it 'does not trigger the pause event', ->
+          expect('pause').not.toHaveBeenTriggeredOn @control
+
+      describe 'when the video is paused', ->
+        beforeEach ->
+          $('.video_control').addClass('pause')
+          spyOnEvent @control, 'play'
+          @control.togglePlayback jQuery.Event('click')
+
+        it 'does not trigger the play event', ->
+          expect('play').not.toHaveBeenTriggeredOn @control
+
+      describe 'when the video is playing', ->
+        beforeEach ->
+          spyOnEvent @control, 'pause'
+          $('.video_control').addClass 'pause'
+          @control.togglePlayback jQuery.Event('click')
+
+        it 'trigger the pause event', ->
+          expect('pause').toHaveBeenTriggeredOn @control
+
+      describe 'when the video is paused', ->
+        beforeEach ->
+          spyOnEvent @control, 'play'
+          $('.video_control').addClass 'play'
+          @control.togglePlayback jQuery.Event('click')
+
+        it 'trigger the play event', ->
+          expect('play').toHaveBeenTriggeredOn @control
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
index ba85f67ac1b06d748cf3e92ed6a15d0c917c300c..d59e936b8c3235a3a6fa3fdb5727a194d277c29b 100644
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
@@ -1,449 +1,450 @@
-#describe 'VideoPlayer', ->
-#  beforeEach ->
-#    jasmine.stubVideoPlayer @, [], false
-#
-#  afterEach ->
-#    YT.Player = undefined
-#
-#  describe 'constructor', ->
-#    beforeEach ->
-#      spyOn window, 'VideoControl'
-#      spyOn YT, 'Player'
-#      $.fn.qtip.andCallFake ->
-#        $(this).data('qtip', true)
-#      $('.video').append $('<div class="add-fullscreen" /><div class="hide-subtitles" />')
-#
-#    describe 'always', ->
-#      beforeEach ->
-#        @player = new VideoPlayer video: @video
-#
-#      it 'instanticate current time to zero', ->
-#        expect(@player.currentTime).toEqual 0
-#
-#      it 'set the element', ->
-#        expect(@player.el).toBe '#video_example'
-#
-#      it 'create video control', ->
-#        expect(window.VideoControl).toHaveBeenCalledWith el: $('.video-controls', @player.el)
-#
-#      it 'create video caption', ->
-#        expect(window.VideoCaption).toHaveBeenCalledWith el: @player.el, youtubeId: 'normalSpeedYoutubeId', currentSpeed: '1.0'
-#
-#      it 'create video speed control', ->
-#        expect(window.VideoSpeedControl).toHaveBeenCalledWith el: $('.secondary-controls', @player.el), speeds: ['0.75', '1.0'], currentSpeed: '1.0'
-#
-#      it 'create video progress slider', ->
-#        expect(window.VideoProgressSlider).toHaveBeenCalledWith el: $('.slider', @player.el)
-#
-#      it 'create Youtube player', ->
-#        expect(YT.Player).toHaveBeenCalledWith 'example'
-#          playerVars:
-#            controls: 0
-#            wmode: 'transparent'
-#            rel: 0
-#            showinfo: 0
-#            enablejsapi: 1
-#          videoId: 'normalSpeedYoutubeId'
-#          events:
-#            onReady: @player.onReady
-#            onStateChange: @player.onStateChange
-#
-#      it 'bind to video control play event', ->
-#        expect($(@player.control)).toHandleWith 'play', @player.play
-#
-#      it 'bind to video control pause event', ->
-#        expect($(@player.control)).toHandleWith 'pause', @player.pause
-#
-#      it 'bind to video caption seek event', ->
-#        expect($(@player.caption)).toHandleWith 'seek', @player.onSeek
-#
-#      it 'bind to video speed control speedChange event', ->
-#        expect($(@player.speedControl)).toHandleWith 'speedChange', @player.onSpeedChange
-#
-#      it 'bind to video progress slider seek event', ->
-#        expect($(@player.progressSlider)).toHandleWith 'seek', @player.onSeek
-#
-#      it 'bind to video volume control volumeChange event', ->
-#        expect($(@player.volumeControl)).toHandleWith 'volumeChange', @player.onVolumeChange
-#
-#      it 'bind to key press', ->
-#        expect($(document)).toHandleWith 'keyup', @player.bindExitFullScreen
-#
-#      it 'bind to fullscreen switching button', ->
-#        expect($('.add-fullscreen')).toHandleWith 'click', @player.toggleFullScreen
-#
-#    describe 'when not on a touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn false
-#        $('.add-fullscreen, .hide-subtitles').removeData 'qtip'
-#        @player = new VideoPlayer video: @video
-#
-#      it 'add the tooltip to fullscreen and subtitle button', ->
-#        expect($('.add-fullscreen')).toHaveData 'qtip'
-#        expect($('.hide-subtitles')).toHaveData 'qtip'
-#
-#      it 'create video volume control', ->
-#        expect(window.VideoVolumeControl).toHaveBeenCalledWith el: $('.secondary-controls', @player.el)
-#
-#    describe 'when on a touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn true
-#        $('.add-fullscreen, .hide-subtitles').removeData 'qtip'
-#        @player = new VideoPlayer video: @video
-#
-#      it 'does not add the tooltip to fullscreen and subtitle button', ->
-#        expect($('.add-fullscreen')).not.toHaveData 'qtip'
-#        expect($('.hide-subtitles')).not.toHaveData 'qtip'
-#
-#      it 'does not create video volume control', ->
-#        expect(window.VideoVolumeControl).not.toHaveBeenCalled()
-#
-#  describe 'onReady', ->
-#    beforeEach ->
-#      @video.embed()
-#      @player = @video.player
-#      spyOnEvent @player, 'ready'
-#      spyOnEvent @player, 'updatePlayTime'
-#      @player.onReady()
-#
-#    describe 'when not on a touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn false
-#        spyOn @player, 'play'
-#        @player.onReady()
-#
-#      it 'autoplay the first video', ->
-#        expect(@player.play).toHaveBeenCalled()
-#
-#    describe 'when on a touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn true
-#        spyOn @player, 'play'
-#        @player.onReady()
-#
-#      it 'does not autoplay the first video', ->
-#        expect(@player.play).not.toHaveBeenCalled()
-#
-#  describe 'onStateChange', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#
-#    describe 'when the video is unstarted', ->
-#      beforeEach ->
-#        spyOn @player.control, 'pause'
-#        @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
-#        @player.onStateChange data: YT.PlayerState.UNSTARTED
-#
-#      it 'pause the video control', ->
-#        expect(@player.control.pause).toHaveBeenCalled()
-#
-#      it 'pause the video caption', ->
-#        expect(@player.caption.pause).toHaveBeenCalled()
-#
-#    describe 'when the video is playing', ->
-#      beforeEach ->
-#        @anotherPlayer = jasmine.createSpyObj 'AnotherPlayer', ['pauseVideo']
-#        window.player = @anotherPlayer
-#        spyOn @video, 'log'
-#        spyOn(window, 'setInterval').andReturn 100
-#        spyOn @player.control, 'play'
-#        @player.caption.play = jasmine.createSpy('VideoCaption.play')
-#        @player.progressSlider.play = jasmine.createSpy('VideoProgressSlider.play')
-#        @player.player.getVideoEmbedCode.andReturn 'embedCode'
-#        @player.onStateChange data: YT.PlayerState.PLAYING
-#
-#      it 'log the play_video event', ->
-#        expect(@video.log).toHaveBeenCalledWith 'play_video'
-#
-#      it 'pause other video player', ->
-#        expect(@anotherPlayer.pauseVideo).toHaveBeenCalled()
-#
-#      it 'set current video player as active player', ->
-#        expect(window.player).toEqual @player.player
-#
-#      it 'set update interval', ->
-#        expect(window.setInterval).toHaveBeenCalledWith @player.update, 200
-#        expect(@player.player.interval).toEqual 100
-#
-#      it 'play the video control', ->
-#        expect(@player.control.play).toHaveBeenCalled()
-#
-#      it 'play the video caption', ->
-#        expect(@player.caption.play).toHaveBeenCalled()
-#
-#      it 'play the video progress slider', ->
-#        expect(@player.progressSlider.play).toHaveBeenCalled()
-#
-#    describe 'when the video is paused', ->
-#      beforeEach ->
-#        @player = new VideoPlayer video: @video
-#        window.player = @player.player
-#        spyOn @video, 'log'
-#        spyOn window, 'clearInterval'
-#        spyOn @player.control, 'pause'
-#        @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
-#        @player.player.interval = 100
-#        @player.player.getVideoEmbedCode.andReturn 'embedCode'
-#        @player.onStateChange data: YT.PlayerState.PAUSED
-#
-#      it 'log the pause_video event', ->
-#        expect(@video.log).toHaveBeenCalledWith 'pause_video'
-#
-#      it 'set current video player as inactive', ->
-#        expect(window.player).toBeNull()
-#
-#      it 'clear update interval', ->
-#        expect(window.clearInterval).toHaveBeenCalledWith 100
-#        expect(@player.player.interval).toBeNull()
-#
-#      it 'pause the video control', ->
-#        expect(@player.control.pause).toHaveBeenCalled()
-#
-#      it 'pause the video caption', ->
-#        expect(@player.caption.pause).toHaveBeenCalled()
-#
-#    describe 'when the video is ended', ->
-#      beforeEach ->
-#        spyOn @player.control, 'pause'
-#        @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
-#        @player.onStateChange data: YT.PlayerState.ENDED
-#
-#      it 'pause the video control', ->
-#        expect(@player.control.pause).toHaveBeenCalled()
-#
-#      it 'pause the video caption', ->
-#        expect(@player.caption.pause).toHaveBeenCalled()
-#
-#  describe 'onSeek', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      spyOn window, 'clearInterval'
-#      @player.player.interval = 100
-#      spyOn @player, 'updatePlayTime'
-#      @player.onSeek {}, 60
-#
-#    it 'seek the player', ->
-#      expect(@player.player.seekTo).toHaveBeenCalledWith 60, true
-#
-#    it 'call updatePlayTime on player', ->
-#      expect(@player.updatePlayTime).toHaveBeenCalledWith 60
-#
-#    describe 'when the player is playing', ->
-#      beforeEach ->
-#        @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
-#        @player.onSeek {}, 60
-#
-#      it 'reset the update interval', ->
-#        expect(window.clearInterval).toHaveBeenCalledWith 100
-#
-#    describe 'when the player is not playing', ->
-#      beforeEach ->
-#        @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
-#        @player.onSeek {}, 60
-#
-#      it 'set the current time', ->
-#        expect(@player.currentTime).toEqual 60
-#
-#  describe 'onSpeedChange', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      @player.currentTime = 60
-#      spyOn @player, 'updatePlayTime'
-#      spyOn(@video, 'setSpeed').andCallThrough()
-#
-#    describe 'always', ->
-#      beforeEach ->
-#        @player.onSpeedChange {}, '0.75'
-#
-#      it 'convert the current time to the new speed', ->
-#        expect(@player.currentTime).toEqual '80.000'
-#
-#      it 'set video speed to the new speed', ->
-#        expect(@video.setSpeed).toHaveBeenCalledWith '0.75'
-#
-#      it 'tell video caption that the speed has changed', ->
-#        expect(@player.caption.currentSpeed).toEqual '0.75'
-#
-#    describe 'when the video is playing', ->
-#      beforeEach ->
-#        @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
-#        @player.onSpeedChange {}, '0.75'
-#
-#      it 'load the video', ->
-#        expect(@player.player.loadVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
-#
-#      it 'trigger updatePlayTime event', ->
-#        expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
-#
-#    describe 'when the video is not playing', ->
-#      beforeEach ->
-#        @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
-#        @player.onSpeedChange {}, '0.75'
-#
-#      it 'cue the video', ->
-#        expect(@player.player.cueVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
-#
-#      it 'trigger updatePlayTime event', ->
-#        expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
-#
-#  describe 'onVolumeChange', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      @player.onVolumeChange undefined, 60
-#
-#    it 'set the volume on player', ->
-#      expect(@player.player.setVolume).toHaveBeenCalledWith 60
-#
-#  describe 'update', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      spyOn @player, 'updatePlayTime'
-#
-#    describe 'when the current time is unavailable from the player', ->
-#      beforeEach ->
-#        @player.player.getCurrentTime.andReturn undefined
-#        @player.update()
-#
-#      it 'does not trigger updatePlayTime event', ->
-#        expect(@player.updatePlayTime).not.toHaveBeenCalled()
-#
-#    describe 'when the current time is available from the player', ->
-#      beforeEach ->
-#        @player.player.getCurrentTime.andReturn 60
-#        @player.update()
-#
-#      it 'trigger updatePlayTime event', ->
-#        expect(@player.updatePlayTime).toHaveBeenCalledWith(60)
-#
-#  describe 'updatePlayTime', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      spyOn(@video, 'getDuration').andReturn 1800
-#      @player.caption.updatePlayTime = jasmine.createSpy('VideoCaption.updatePlayTime')
-#      @player.progressSlider.updatePlayTime = jasmine.createSpy('VideoProgressSlider.updatePlayTime')
-#      @player.updatePlayTime 60
-#
-#    it 'update the video playback time', ->
-#      expect($('.vidtime')).toHaveHtml '1:00 / 30:00'
-#
-#    it 'update the playback time on caption', ->
-#      expect(@player.caption.updatePlayTime).toHaveBeenCalledWith 60
-#
-#    it 'update the playback time on progress slider', ->
-#      expect(@player.progressSlider.updatePlayTime).toHaveBeenCalledWith 60, 1800
-#
-#  describe 'toggleFullScreen', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      @player.caption.resize = jasmine.createSpy('VideoCaption.resize')
-#
-#    describe 'when the video player is not full screen', ->
-#      beforeEach ->
-#        @player.el.removeClass 'fullscreen'
-#        @player.toggleFullScreen(jQuery.Event("click"))
-#
-#      it 'replace the full screen button tooltip', ->
-#        expect($('.add-fullscreen')).toHaveAttr 'title', 'Exit fill browser'
-#
-#      it 'add a new exit from fullscreen button', ->
-#        expect(@player.el).toContain 'a.exit'
-#
-#      it 'add the fullscreen class', ->
-#        expect(@player.el).toHaveClass 'fullscreen'
-#
-#      it 'tell VideoCaption to resize', ->
-#        expect(@player.caption.resize).toHaveBeenCalled()
-#
-#    describe 'when the video player already full screen', ->
-#      beforeEach ->
-#        @player.el.addClass 'fullscreen'
-#        @player.toggleFullScreen(jQuery.Event("click"))
-#
-#      it 'replace the full screen button tooltip', ->
-#        expect($('.add-fullscreen')).toHaveAttr 'title', 'Fill browser'
-#
-#      it 'remove exit full screen button', ->
-#        expect(@player.el).not.toContain 'a.exit'
-#
-#      it 'remove the fullscreen class', ->
-#        expect(@player.el).not.toHaveClass 'fullscreen'
-#
-#      it 'tell VideoCaption to resize', ->
-#        expect(@player.caption.resize).toHaveBeenCalled()
-#
-#  describe 'play', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#
-#    describe 'when the player is not ready', ->
-#      beforeEach ->
-#        @player.player.playVideo = undefined
-#        @player.play()
-#
-#      it 'does nothing', ->
-#        expect(@player.player.playVideo).toBeUndefined()
-#
-#    describe 'when the player is ready', ->
-#      beforeEach ->
-#        @player.player.playVideo.andReturn true
-#        @player.play()
-#
-#      it 'delegate to the Youtube player', ->
-#        expect(@player.player.playVideo).toHaveBeenCalled()
-#
-#  describe 'isPlaying', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#
-#    describe 'when the video is playing', ->
-#      beforeEach ->
-#        @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
-#
-#      it 'return true', ->
-#        expect(@player.isPlaying()).toBeTruthy()
-#
-#    describe 'when the video is not playing', ->
-#      beforeEach ->
-#        @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
-#
-#      it 'return false', ->
-#        expect(@player.isPlaying()).toBeFalsy()
-#
-#  describe 'pause', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      @player.pause()
-#
-#    it 'delegate to the Youtube player', ->
-#      expect(@player.player.pauseVideo).toHaveBeenCalled()
-#
-#  describe 'duration', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      spyOn @video, 'getDuration'
-#      @player.duration()
-#
-#    it 'delegate to the video', ->
-#      expect(@video.getDuration).toHaveBeenCalled()
-#
-#  describe 'currentSpeed', ->
-#    beforeEach ->
-#      @player = new VideoPlayer video: @video
-#      @video.speed = '3.0'
-#
-#    it 'delegate to the video', ->
-#      expect(@player.currentSpeed()).toEqual '3.0'
-#
-#  describe 'volume', ->
-#    beforeEach ->
-#      @player = new VideoPlayer @video
-#      @player.player.getVolume.andReturn 42
-#
-#    describe 'without value', ->
-#      it 'return current volume', ->
-#        expect(@player.volume()).toEqual 42
-#
-#    describe 'with value', ->
-#      it 'set player volume', ->
-#        @player.volume(60)
-#        expect(@player.player.setVolume).toHaveBeenCalledWith(60)
+# TODO: figure out why failing
+xdescribe 'VideoPlayer', ->
+  beforeEach ->
+    jasmine.stubVideoPlayer @, [], false
+
+  afterEach ->
+    YT.Player = undefined
+
+  describe 'constructor', ->
+    beforeEach ->
+      spyOn window, 'VideoControl'
+      spyOn YT, 'Player'
+      $.fn.qtip.andCallFake ->
+        $(this).data('qtip', true)
+      $('.video').append $('<div class="add-fullscreen" /><div class="hide-subtitles" />')
+
+    describe 'always', ->
+      beforeEach ->
+        @player = new VideoPlayer video: @video
+
+      it 'instanticate current time to zero', ->
+        expect(@player.currentTime).toEqual 0
+
+      it 'set the element', ->
+        expect(@player.el).toBe '#video_example'
+
+      it 'create video control', ->
+        expect(window.VideoControl).toHaveBeenCalledWith el: $('.video-controls', @player.el)
+
+      it 'create video caption', ->
+        expect(window.VideoCaption).toHaveBeenCalledWith el: @player.el, youtubeId: 'normalSpeedYoutubeId', currentSpeed: '1.0'
+
+      it 'create video speed control', ->
+        expect(window.VideoSpeedControl).toHaveBeenCalledWith el: $('.secondary-controls', @player.el), speeds: ['0.75', '1.0'], currentSpeed: '1.0'
+
+      it 'create video progress slider', ->
+        expect(window.VideoProgressSlider).toHaveBeenCalledWith el: $('.slider', @player.el)
+
+      it 'create Youtube player', ->
+        expect(YT.Player).toHaveBeenCalledWith 'example'
+          playerVars:
+            controls: 0
+            wmode: 'transparent'
+            rel: 0
+            showinfo: 0
+            enablejsapi: 1
+          videoId: 'normalSpeedYoutubeId'
+          events:
+            onReady: @player.onReady
+            onStateChange: @player.onStateChange
+
+      it 'bind to video control play event', ->
+        expect($(@player.control)).toHandleWith 'play', @player.play
+
+      it 'bind to video control pause event', ->
+        expect($(@player.control)).toHandleWith 'pause', @player.pause
+
+      it 'bind to video caption seek event', ->
+        expect($(@player.caption)).toHandleWith 'seek', @player.onSeek
+
+      it 'bind to video speed control speedChange event', ->
+        expect($(@player.speedControl)).toHandleWith 'speedChange', @player.onSpeedChange
+
+      it 'bind to video progress slider seek event', ->
+        expect($(@player.progressSlider)).toHandleWith 'seek', @player.onSeek
+
+      it 'bind to video volume control volumeChange event', ->
+        expect($(@player.volumeControl)).toHandleWith 'volumeChange', @player.onVolumeChange
+
+      it 'bind to key press', ->
+        expect($(document)).toHandleWith 'keyup', @player.bindExitFullScreen
+
+      it 'bind to fullscreen switching button', ->
+        expect($('.add-fullscreen')).toHandleWith 'click', @player.toggleFullScreen
+
+    describe 'when not on a touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn false
+        $('.add-fullscreen, .hide-subtitles').removeData 'qtip'
+        @player = new VideoPlayer video: @video
+
+      it 'add the tooltip to fullscreen and subtitle button', ->
+        expect($('.add-fullscreen')).toHaveData 'qtip'
+        expect($('.hide-subtitles')).toHaveData 'qtip'
+
+      it 'create video volume control', ->
+        expect(window.VideoVolumeControl).toHaveBeenCalledWith el: $('.secondary-controls', @player.el)
+
+    describe 'when on a touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn true
+        $('.add-fullscreen, .hide-subtitles').removeData 'qtip'
+        @player = new VideoPlayer video: @video
+
+      it 'does not add the tooltip to fullscreen and subtitle button', ->
+        expect($('.add-fullscreen')).not.toHaveData 'qtip'
+        expect($('.hide-subtitles')).not.toHaveData 'qtip'
+
+      it 'does not create video volume control', ->
+        expect(window.VideoVolumeControl).not.toHaveBeenCalled()
+
+  describe 'onReady', ->
+    beforeEach ->
+      @video.embed()
+      @player = @video.player
+      spyOnEvent @player, 'ready'
+      spyOnEvent @player, 'updatePlayTime'
+      @player.onReady()
+
+    describe 'when not on a touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn false
+        spyOn @player, 'play'
+        @player.onReady()
+
+      it 'autoplay the first video', ->
+        expect(@player.play).toHaveBeenCalled()
+
+    describe 'when on a touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn true
+        spyOn @player, 'play'
+        @player.onReady()
+
+      it 'does not autoplay the first video', ->
+        expect(@player.play).not.toHaveBeenCalled()
+
+  describe 'onStateChange', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+
+    describe 'when the video is unstarted', ->
+      beforeEach ->
+        spyOn @player.control, 'pause'
+        @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
+        @player.onStateChange data: YT.PlayerState.UNSTARTED
+
+      it 'pause the video control', ->
+        expect(@player.control.pause).toHaveBeenCalled()
+
+      it 'pause the video caption', ->
+        expect(@player.caption.pause).toHaveBeenCalled()
+
+    describe 'when the video is playing', ->
+      beforeEach ->
+        @anotherPlayer = jasmine.createSpyObj 'AnotherPlayer', ['pauseVideo']
+        window.player = @anotherPlayer
+        spyOn @video, 'log'
+        spyOn(window, 'setInterval').andReturn 100
+        spyOn @player.control, 'play'
+        @player.caption.play = jasmine.createSpy('VideoCaption.play')
+        @player.progressSlider.play = jasmine.createSpy('VideoProgressSlider.play')
+        @player.player.getVideoEmbedCode.andReturn 'embedCode'
+        @player.onStateChange data: YT.PlayerState.PLAYING
+
+      it 'log the play_video event', ->
+        expect(@video.log).toHaveBeenCalledWith 'play_video'
+
+      it 'pause other video player', ->
+        expect(@anotherPlayer.pauseVideo).toHaveBeenCalled()
+
+      it 'set current video player as active player', ->
+        expect(window.player).toEqual @player.player
+
+      it 'set update interval', ->
+        expect(window.setInterval).toHaveBeenCalledWith @player.update, 200
+        expect(@player.player.interval).toEqual 100
+
+      it 'play the video control', ->
+        expect(@player.control.play).toHaveBeenCalled()
+
+      it 'play the video caption', ->
+        expect(@player.caption.play).toHaveBeenCalled()
+
+      it 'play the video progress slider', ->
+        expect(@player.progressSlider.play).toHaveBeenCalled()
+
+    describe 'when the video is paused', ->
+      beforeEach ->
+        @player = new VideoPlayer video: @video
+        window.player = @player.player
+        spyOn @video, 'log'
+        spyOn window, 'clearInterval'
+        spyOn @player.control, 'pause'
+        @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
+        @player.player.interval = 100
+        @player.player.getVideoEmbedCode.andReturn 'embedCode'
+        @player.onStateChange data: YT.PlayerState.PAUSED
+
+      it 'log the pause_video event', ->
+        expect(@video.log).toHaveBeenCalledWith 'pause_video'
+
+      it 'set current video player as inactive', ->
+        expect(window.player).toBeNull()
+
+      it 'clear update interval', ->
+        expect(window.clearInterval).toHaveBeenCalledWith 100
+        expect(@player.player.interval).toBeNull()
+
+      it 'pause the video control', ->
+        expect(@player.control.pause).toHaveBeenCalled()
+
+      it 'pause the video caption', ->
+        expect(@player.caption.pause).toHaveBeenCalled()
+
+    describe 'when the video is ended', ->
+      beforeEach ->
+        spyOn @player.control, 'pause'
+        @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
+        @player.onStateChange data: YT.PlayerState.ENDED
+
+      it 'pause the video control', ->
+        expect(@player.control.pause).toHaveBeenCalled()
+
+      it 'pause the video caption', ->
+        expect(@player.caption.pause).toHaveBeenCalled()
+
+  describe 'onSeek', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      spyOn window, 'clearInterval'
+      @player.player.interval = 100
+      spyOn @player, 'updatePlayTime'
+      @player.onSeek {}, 60
+
+    it 'seek the player', ->
+      expect(@player.player.seekTo).toHaveBeenCalledWith 60, true
+
+    it 'call updatePlayTime on player', ->
+      expect(@player.updatePlayTime).toHaveBeenCalledWith 60
+
+    describe 'when the player is playing', ->
+      beforeEach ->
+        @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
+        @player.onSeek {}, 60
+
+      it 'reset the update interval', ->
+        expect(window.clearInterval).toHaveBeenCalledWith 100
+
+    describe 'when the player is not playing', ->
+      beforeEach ->
+        @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
+        @player.onSeek {}, 60
+
+      it 'set the current time', ->
+        expect(@player.currentTime).toEqual 60
+
+  describe 'onSpeedChange', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      @player.currentTime = 60
+      spyOn @player, 'updatePlayTime'
+      spyOn(@video, 'setSpeed').andCallThrough()
+
+    describe 'always', ->
+      beforeEach ->
+        @player.onSpeedChange {}, '0.75'
+
+      it 'convert the current time to the new speed', ->
+        expect(@player.currentTime).toEqual '80.000'
+
+      it 'set video speed to the new speed', ->
+        expect(@video.setSpeed).toHaveBeenCalledWith '0.75'
+
+      it 'tell video caption that the speed has changed', ->
+        expect(@player.caption.currentSpeed).toEqual '0.75'
+
+    describe 'when the video is playing', ->
+      beforeEach ->
+        @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
+        @player.onSpeedChange {}, '0.75'
+
+      it 'load the video', ->
+        expect(@player.player.loadVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
+
+      it 'trigger updatePlayTime event', ->
+        expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
+
+    describe 'when the video is not playing', ->
+      beforeEach ->
+        @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
+        @player.onSpeedChange {}, '0.75'
+
+      it 'cue the video', ->
+        expect(@player.player.cueVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
+
+      it 'trigger updatePlayTime event', ->
+        expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
+
+  describe 'onVolumeChange', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      @player.onVolumeChange undefined, 60
+
+    it 'set the volume on player', ->
+      expect(@player.player.setVolume).toHaveBeenCalledWith 60
+
+  describe 'update', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      spyOn @player, 'updatePlayTime'
+
+    describe 'when the current time is unavailable from the player', ->
+      beforeEach ->
+        @player.player.getCurrentTime.andReturn undefined
+        @player.update()
+
+      it 'does not trigger updatePlayTime event', ->
+        expect(@player.updatePlayTime).not.toHaveBeenCalled()
+
+    describe 'when the current time is available from the player', ->
+      beforeEach ->
+        @player.player.getCurrentTime.andReturn 60
+        @player.update()
+
+      it 'trigger updatePlayTime event', ->
+        expect(@player.updatePlayTime).toHaveBeenCalledWith(60)
+
+  describe 'updatePlayTime', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      spyOn(@video, 'getDuration').andReturn 1800
+      @player.caption.updatePlayTime = jasmine.createSpy('VideoCaption.updatePlayTime')
+      @player.progressSlider.updatePlayTime = jasmine.createSpy('VideoProgressSlider.updatePlayTime')
+      @player.updatePlayTime 60
+
+    it 'update the video playback time', ->
+      expect($('.vidtime')).toHaveHtml '1:00 / 30:00'
+
+    it 'update the playback time on caption', ->
+      expect(@player.caption.updatePlayTime).toHaveBeenCalledWith 60
+
+    it 'update the playback time on progress slider', ->
+      expect(@player.progressSlider.updatePlayTime).toHaveBeenCalledWith 60, 1800
+
+  describe 'toggleFullScreen', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      @player.caption.resize = jasmine.createSpy('VideoCaption.resize')
+
+    describe 'when the video player is not full screen', ->
+      beforeEach ->
+        @player.el.removeClass 'fullscreen'
+        @player.toggleFullScreen(jQuery.Event("click"))
+
+      it 'replace the full screen button tooltip', ->
+        expect($('.add-fullscreen')).toHaveAttr 'title', 'Exit fill browser'
+
+      it 'add a new exit from fullscreen button', ->
+        expect(@player.el).toContain 'a.exit'
+
+      it 'add the fullscreen class', ->
+        expect(@player.el).toHaveClass 'fullscreen'
+
+      it 'tell VideoCaption to resize', ->
+        expect(@player.caption.resize).toHaveBeenCalled()
+
+    describe 'when the video player already full screen', ->
+      beforeEach ->
+        @player.el.addClass 'fullscreen'
+        @player.toggleFullScreen(jQuery.Event("click"))
+
+      it 'replace the full screen button tooltip', ->
+        expect($('.add-fullscreen')).toHaveAttr 'title', 'Fill browser'
+
+      it 'remove exit full screen button', ->
+        expect(@player.el).not.toContain 'a.exit'
+
+      it 'remove the fullscreen class', ->
+        expect(@player.el).not.toHaveClass 'fullscreen'
+
+      it 'tell VideoCaption to resize', ->
+        expect(@player.caption.resize).toHaveBeenCalled()
+
+  describe 'play', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+
+    describe 'when the player is not ready', ->
+      beforeEach ->
+        @player.player.playVideo = undefined
+        @player.play()
+
+      it 'does nothing', ->
+        expect(@player.player.playVideo).toBeUndefined()
+
+    describe 'when the player is ready', ->
+      beforeEach ->
+        @player.player.playVideo.andReturn true
+        @player.play()
+
+      it 'delegate to the Youtube player', ->
+        expect(@player.player.playVideo).toHaveBeenCalled()
+
+  describe 'isPlaying', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+
+    describe 'when the video is playing', ->
+      beforeEach ->
+        @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
+
+      it 'return true', ->
+        expect(@player.isPlaying()).toBeTruthy()
+
+    describe 'when the video is not playing', ->
+      beforeEach ->
+        @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
+
+      it 'return false', ->
+        expect(@player.isPlaying()).toBeFalsy()
+
+  describe 'pause', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      @player.pause()
+
+    it 'delegate to the Youtube player', ->
+      expect(@player.player.pauseVideo).toHaveBeenCalled()
+
+  describe 'duration', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      spyOn @video, 'getDuration'
+      @player.duration()
+
+    it 'delegate to the video', ->
+      expect(@video.getDuration).toHaveBeenCalled()
+
+  describe 'currentSpeed', ->
+    beforeEach ->
+      @player = new VideoPlayer video: @video
+      @video.speed = '3.0'
+
+    it 'delegate to the video', ->
+      expect(@player.currentSpeed()).toEqual '3.0'
+
+  describe 'volume', ->
+    beforeEach ->
+      @player = new VideoPlayer @video
+      @player.player.getVolume.andReturn 42
+
+    describe 'without value', ->
+      it 'return current volume', ->
+        expect(@player.volume()).toEqual 42
+
+    describe 'with value', ->
+      it 'set player volume', ->
+        @player.volume(60)
+        expect(@player.player.setVolume).toHaveBeenCalledWith(60)
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
index 58dfc8782a0a7d3ad4fa78fcea695edcbc181f36..99b675b1d73aa2a41da7ccdc0b6268ee04e63ac1 100644
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
@@ -1,160 +1,161 @@
-#describe 'VideoProgressSlider', ->
-#  beforeEach ->
-#    jasmine.stubVideoPlayer @
-#
-#  describe 'constructor', ->
-#    describe 'on a non-touch based device', ->
-#      beforeEach ->
-#        spyOn($.fn, 'slider').andCallThrough()
-#        spyOn(window, 'onTouchBasedDevice').andReturn false
-#        @slider = new VideoProgressSlider el: $('.slider')
-#
-#      it 'build the slider', ->
-#        expect(@slider.slider).toBe '.slider'
-#        expect($.fn.slider).toHaveBeenCalledWith
-#          range: 'min'
-#          change: @slider.onChange
-#          slide: @slider.onSlide
-#          stop: @slider.onStop
-#
-#      it 'build the seek handle', ->
-#        expect(@slider.handle).toBe '.slider .ui-slider-handle'
-#        expect($.fn.qtip).toHaveBeenCalledWith
-#          content: "0:00"
-#          position:
-#            my: 'bottom center'
-#            at: 'top center'
-#            container: @slider.handle
-#          hide:
-#            delay: 700
-#          style:
-#            classes: 'ui-tooltip-slider'
-#            widget: true
-#
-#    describe 'on a touch-based device', ->
-#      beforeEach ->
-#        spyOn($.fn, 'slider').andCallThrough()
-#        spyOn(window, 'onTouchBasedDevice').andReturn true
-#        @slider = new VideoProgressSlider el: $('.slider')
-#
-#      it 'does not build the slider', ->
-#        expect(@slider.slider).toBeUndefined
-#        expect($.fn.slider).not.toHaveBeenCalled()
-#
-#  describe 'play', ->
-#    beforeEach ->
-#      @slider = new VideoProgressSlider el: $('.slider')
-#      spyOn($.fn, 'slider').andCallThrough()
-#
-#    describe 'when the slider was already built', ->
-#      beforeEach ->
-#        @slider.play()
-#
-#      it 'does not build the slider', ->
-#        expect($.fn.slider).not.toHaveBeenCalled
-#
-#    describe 'when the slider was not already built', ->
-#      beforeEach ->
-#        @slider.slider = null
-#        @slider.play()
-#
-#      it 'build the slider', ->
-#        expect(@slider.slider).toBe '.slider'
-#        expect($.fn.slider).toHaveBeenCalledWith
-#          range: 'min'
-#          change: @slider.onChange
-#          slide: @slider.onSlide
-#          stop: @slider.onStop
-#
-#      it 'build the seek handle', ->
-#        expect(@slider.handle).toBe '.ui-slider-handle'
-#        expect($.fn.qtip).toHaveBeenCalledWith
-#          content: "0:00"
-#          position:
-#            my: 'bottom center'
-#            at: 'top center'
-#            container: @slider.handle
-#          hide:
-#            delay: 700
-#          style:
-#            classes: 'ui-tooltip-slider'
-#            widget: true
-#
-#  describe 'updatePlayTime', ->
-#    beforeEach ->
-#      @slider = new VideoProgressSlider el: $('.slider')
-#      spyOn($.fn, 'slider').andCallThrough()
-#
-#    describe 'when frozen', ->
-#      beforeEach ->
-#        @slider.frozen = true
-#        @slider.updatePlayTime 20, 120
-#
-#      it 'does not update the slider', ->
-#        expect($.fn.slider).not.toHaveBeenCalled()
-#
-#    describe 'when not frozen', ->
-#      beforeEach ->
-#        @slider.frozen = false
-#        @slider.updatePlayTime 20, 120
-#
-#      it 'update the max value of the slider', ->
-#        expect($.fn.slider).toHaveBeenCalledWith 'option', 'max', 120
-#
-#      it 'update current value of the slider', ->
-#        expect($.fn.slider).toHaveBeenCalledWith 'value', 20
-#
-#  describe 'onSlide', ->
-#    beforeEach ->
-#      @slider = new VideoProgressSlider el: $('.slider')
-#      @time = null
-#      $(@slider).bind 'seek', (event, time) => @time = time
-#      spyOnEvent @slider, 'seek'
-#      @slider.onSlide {}, value: 20
-#
-#    it 'freeze the slider', ->
-#      expect(@slider.frozen).toBeTruthy()
-#
-#    it 'update the tooltip', ->
-#      expect($.fn.qtip).toHaveBeenCalled()
-#
-#    it 'trigger seek event', ->
-#      expect('seek').toHaveBeenTriggeredOn @slider
-#      expect(@time).toEqual 20
-#
-#  describe 'onChange', ->
-#    beforeEach ->
-#      @slider = new VideoProgressSlider el: $('.slider')
-#      @slider.onChange {}, value: 20
-#
-#    it 'update the tooltip', ->
-#      expect($.fn.qtip).toHaveBeenCalled()
-#
-#  describe 'onStop', ->
-#    beforeEach ->
-#      @slider = new VideoProgressSlider el: $('.slider')
-#      @time = null
-#      $(@slider).bind 'seek', (event, time) => @time = time
-#      spyOnEvent @slider, 'seek'
-#      spyOn(window, 'setTimeout')
-#      @slider.onStop {}, value: 20
-#
-#    it 'freeze the slider', ->
-#      expect(@slider.frozen).toBeTruthy()
-#
-#    it 'trigger seek event', ->
-#      expect('seek').toHaveBeenTriggeredOn @slider
-#      expect(@time).toEqual 20
-#
-#    it 'set timeout to unfreeze the slider', ->
-#      expect(window.setTimeout).toHaveBeenCalledWith jasmine.any(Function), 200
-#      window.setTimeout.mostRecentCall.args[0]()
-#      expect(@slider.frozen).toBeFalsy()
-#
-#  describe 'updateTooltip', ->
-#    beforeEach ->
-#      @slider = new VideoProgressSlider el: $('.slider')
-#      @slider.updateTooltip 90
-#
-#    it 'set the tooltip value', ->
-#      expect($.fn.qtip).toHaveBeenCalledWith 'option', 'content.text', '1:30'
+# TODO: figure out why failing
+xdescribe 'VideoProgressSlider', ->
+  beforeEach ->
+    jasmine.stubVideoPlayer @
+
+  describe 'constructor', ->
+    describe 'on a non-touch based device', ->
+      beforeEach ->
+        spyOn($.fn, 'slider').andCallThrough()
+        spyOn(window, 'onTouchBasedDevice').andReturn false
+        @slider = new VideoProgressSlider el: $('.slider')
+
+      it 'build the slider', ->
+        expect(@slider.slider).toBe '.slider'
+        expect($.fn.slider).toHaveBeenCalledWith
+          range: 'min'
+          change: @slider.onChange
+          slide: @slider.onSlide
+          stop: @slider.onStop
+
+      it 'build the seek handle', ->
+        expect(@slider.handle).toBe '.slider .ui-slider-handle'
+        expect($.fn.qtip).toHaveBeenCalledWith
+          content: "0:00"
+          position:
+            my: 'bottom center'
+            at: 'top center'
+            container: @slider.handle
+          hide:
+            delay: 700
+          style:
+            classes: 'ui-tooltip-slider'
+            widget: true
+
+    describe 'on a touch-based device', ->
+      beforeEach ->
+        spyOn($.fn, 'slider').andCallThrough()
+        spyOn(window, 'onTouchBasedDevice').andReturn true
+        @slider = new VideoProgressSlider el: $('.slider')
+
+      it 'does not build the slider', ->
+        expect(@slider.slider).toBeUndefined
+        expect($.fn.slider).not.toHaveBeenCalled()
+
+  describe 'play', ->
+    beforeEach ->
+      @slider = new VideoProgressSlider el: $('.slider')
+      spyOn($.fn, 'slider').andCallThrough()
+
+    describe 'when the slider was already built', ->
+      beforeEach ->
+        @slider.play()
+
+      it 'does not build the slider', ->
+        expect($.fn.slider).not.toHaveBeenCalled
+
+    describe 'when the slider was not already built', ->
+      beforeEach ->
+        @slider.slider = null
+        @slider.play()
+
+      it 'build the slider', ->
+        expect(@slider.slider).toBe '.slider'
+        expect($.fn.slider).toHaveBeenCalledWith
+          range: 'min'
+          change: @slider.onChange
+          slide: @slider.onSlide
+          stop: @slider.onStop
+
+      it 'build the seek handle', ->
+        expect(@slider.handle).toBe '.ui-slider-handle'
+        expect($.fn.qtip).toHaveBeenCalledWith
+          content: "0:00"
+          position:
+            my: 'bottom center'
+            at: 'top center'
+            container: @slider.handle
+          hide:
+            delay: 700
+          style:
+            classes: 'ui-tooltip-slider'
+            widget: true
+
+  describe 'updatePlayTime', ->
+    beforeEach ->
+      @slider = new VideoProgressSlider el: $('.slider')
+      spyOn($.fn, 'slider').andCallThrough()
+
+    describe 'when frozen', ->
+      beforeEach ->
+        @slider.frozen = true
+        @slider.updatePlayTime 20, 120
+
+      it 'does not update the slider', ->
+        expect($.fn.slider).not.toHaveBeenCalled()
+
+    describe 'when not frozen', ->
+      beforeEach ->
+        @slider.frozen = false
+        @slider.updatePlayTime 20, 120
+
+      it 'update the max value of the slider', ->
+        expect($.fn.slider).toHaveBeenCalledWith 'option', 'max', 120
+
+      it 'update current value of the slider', ->
+        expect($.fn.slider).toHaveBeenCalledWith 'value', 20
+
+  describe 'onSlide', ->
+    beforeEach ->
+      @slider = new VideoProgressSlider el: $('.slider')
+      @time = null
+      $(@slider).bind 'seek', (event, time) => @time = time
+      spyOnEvent @slider, 'seek'
+      @slider.onSlide {}, value: 20
+
+    it 'freeze the slider', ->
+      expect(@slider.frozen).toBeTruthy()
+
+    it 'update the tooltip', ->
+      expect($.fn.qtip).toHaveBeenCalled()
+
+    it 'trigger seek event', ->
+      expect('seek').toHaveBeenTriggeredOn @slider
+      expect(@time).toEqual 20
+
+  describe 'onChange', ->
+    beforeEach ->
+      @slider = new VideoProgressSlider el: $('.slider')
+      @slider.onChange {}, value: 20
+
+    it 'update the tooltip', ->
+      expect($.fn.qtip).toHaveBeenCalled()
+
+  describe 'onStop', ->
+    beforeEach ->
+      @slider = new VideoProgressSlider el: $('.slider')
+      @time = null
+      $(@slider).bind 'seek', (event, time) => @time = time
+      spyOnEvent @slider, 'seek'
+      spyOn(window, 'setTimeout')
+      @slider.onStop {}, value: 20
+
+    it 'freeze the slider', ->
+      expect(@slider.frozen).toBeTruthy()
+
+    it 'trigger seek event', ->
+      expect('seek').toHaveBeenTriggeredOn @slider
+      expect(@time).toEqual 20
+
+    it 'set timeout to unfreeze the slider', ->
+      expect(window.setTimeout).toHaveBeenCalledWith jasmine.any(Function), 200
+      window.setTimeout.mostRecentCall.args[0]()
+      expect(@slider.frozen).toBeFalsy()
+
+  describe 'updateTooltip', ->
+    beforeEach ->
+      @slider = new VideoProgressSlider el: $('.slider')
+      @slider.updateTooltip 90
+
+    it 'set the tooltip value', ->
+      expect($.fn.qtip).toHaveBeenCalledWith 'option', 'content.text', '1:30'
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
index 14c45815f92d71117011aa1999a82e6bab6979ab..a7af239094f97cc063f9909c915359ba68ec2ff1 100644
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
@@ -1,90 +1,91 @@
-#describe 'VideoSpeedControl', ->
-#  beforeEach ->
-#    jasmine.stubVideoPlayer @
-#    $('.speeds').remove()
-#
-#  describe 'constructor', ->
-#    describe 'always', ->
-#      beforeEach ->
-#        @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-#
-#      it 'add the video speed control to player', ->
-#        expect($('.secondary-controls').html()).toContain '''
-#          <div class="speeds">
-#            <a href="#">
-#              <h3>Speed</h3>
-#              <p class="active">1.0x</p>
-#            </a>
-#            <ol class="video_speeds"><li data-speed="1.0" class="active"><a href="#">1.0x</a></li><li data-speed="0.75"><a href="#">0.75x</a></li></ol>
-#          </div>
-#        '''
-#
-#      it 'bind to change video speed link', ->
-#        expect($('.video_speeds a')).toHandleWith 'click', @speedControl.changeVideoSpeed
-#
-#    describe 'when running on touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn true
-#        $('.speeds').removeClass 'open'
-#        @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-#
-#      it 'open the speed toggle on click', ->
-#        $('.speeds').click()
-#        expect($('.speeds')).toHaveClass 'open'
-#        $('.speeds').click()
-#        expect($('.speeds')).not.toHaveClass 'open'
-#
-#    describe 'when running on non-touch based device', ->
-#      beforeEach ->
-#        spyOn(window, 'onTouchBasedDevice').andReturn false
-#        $('.speeds').removeClass 'open'
-#        @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-#
-#      it 'open the speed toggle on hover', ->
-#        $('.speeds').mouseenter()
-#        expect($('.speeds')).toHaveClass 'open'
-#        $('.speeds').mouseleave()
-#        expect($('.speeds')).not.toHaveClass 'open'
-#
-#      it 'close the speed toggle on mouse out', ->
-#        $('.speeds').mouseenter().mouseleave()
-#        expect($('.speeds')).not.toHaveClass 'open'
-#
-#      it 'close the speed toggle on click', ->
-#        $('.speeds').mouseenter().click()
-#        expect($('.speeds')).not.toHaveClass 'open'
-#
-#  describe 'changeVideoSpeed', ->
-#    beforeEach ->
-#      @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-#      @video.setSpeed '1.0'
-#
-#    describe 'when new speed is the same', ->
-#      beforeEach ->
-#        spyOnEvent @speedControl, 'speedChange'
-#        $('li[data-speed="1.0"] a').click()
-#
-#      it 'does not trigger speedChange event', ->
-#        expect('speedChange').not.toHaveBeenTriggeredOn @speedControl
-#
-#    describe 'when new speed is not the same', ->
-#      beforeEach ->
-#        @newSpeed = null
-#        $(@speedControl).bind 'speedChange', (event, newSpeed) => @newSpeed = newSpeed
-#        spyOnEvent @speedControl, 'speedChange'
-#        $('li[data-speed="0.75"] a').click()
-#
-#      it 'trigger speedChange event', ->
-#        expect('speedChange').toHaveBeenTriggeredOn @speedControl
-#        expect(@newSpeed).toEqual 0.75
-#
-#  describe 'onSpeedChange', ->
-#    beforeEach ->
-#      @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-#      $('li[data-speed="1.0"] a').addClass 'active'
-#      @speedControl.setSpeed '0.75'
-#
-#    it 'set the new speed as active', ->
-#      expect($('.video_speeds li[data-speed="1.0"]')).not.toHaveClass 'active'
-#      expect($('.video_speeds li[data-speed="0.75"]')).toHaveClass 'active'
-#      expect($('.speeds p.active')).toHaveHtml '0.75x'
+# TODO: figure out why failing
+xdescribe 'VideoSpeedControl', ->
+  beforeEach ->
+    jasmine.stubVideoPlayer @
+    $('.speeds').remove()
+
+  describe 'constructor', ->
+    describe 'always', ->
+      beforeEach ->
+        @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
+
+      it 'add the video speed control to player', ->
+        expect($('.secondary-controls').html()).toContain '''
+          <div class="speeds">
+            <a href="#">
+              <h3>Speed</h3>
+              <p class="active">1.0x</p>
+            </a>
+            <ol class="video_speeds"><li data-speed="1.0" class="active"><a href="#">1.0x</a></li><li data-speed="0.75"><a href="#">0.75x</a></li></ol>
+          </div>
+        '''
+
+      it 'bind to change video speed link', ->
+        expect($('.video_speeds a')).toHandleWith 'click', @speedControl.changeVideoSpeed
+
+    describe 'when running on touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn true
+        $('.speeds').removeClass 'open'
+        @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
+
+      it 'open the speed toggle on click', ->
+        $('.speeds').click()
+        expect($('.speeds')).toHaveClass 'open'
+        $('.speeds').click()
+        expect($('.speeds')).not.toHaveClass 'open'
+
+    describe 'when running on non-touch based device', ->
+      beforeEach ->
+        spyOn(window, 'onTouchBasedDevice').andReturn false
+        $('.speeds').removeClass 'open'
+        @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
+
+      it 'open the speed toggle on hover', ->
+        $('.speeds').mouseenter()
+        expect($('.speeds')).toHaveClass 'open'
+        $('.speeds').mouseleave()
+        expect($('.speeds')).not.toHaveClass 'open'
+
+      it 'close the speed toggle on mouse out', ->
+        $('.speeds').mouseenter().mouseleave()
+        expect($('.speeds')).not.toHaveClass 'open'
+
+      it 'close the speed toggle on click', ->
+        $('.speeds').mouseenter().click()
+        expect($('.speeds')).not.toHaveClass 'open'
+
+  describe 'changeVideoSpeed', ->
+    beforeEach ->
+      @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
+      @video.setSpeed '1.0'
+
+    describe 'when new speed is the same', ->
+      beforeEach ->
+        spyOnEvent @speedControl, 'speedChange'
+        $('li[data-speed="1.0"] a').click()
+
+      it 'does not trigger speedChange event', ->
+        expect('speedChange').not.toHaveBeenTriggeredOn @speedControl
+
+    describe 'when new speed is not the same', ->
+      beforeEach ->
+        @newSpeed = null
+        $(@speedControl).bind 'speedChange', (event, newSpeed) => @newSpeed = newSpeed
+        spyOnEvent @speedControl, 'speedChange'
+        $('li[data-speed="0.75"] a').click()
+
+      it 'trigger speedChange event', ->
+        expect('speedChange').toHaveBeenTriggeredOn @speedControl
+        expect(@newSpeed).toEqual 0.75
+
+  describe 'onSpeedChange', ->
+    beforeEach ->
+      @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
+      $('li[data-speed="1.0"] a').addClass 'active'
+      @speedControl.setSpeed '0.75'
+
+    it 'set the new speed as active', ->
+      expect($('.video_speeds li[data-speed="1.0"]')).not.toHaveClass 'active'
+      expect($('.video_speeds li[data-speed="0.75"]')).toHaveClass 'active'
+      expect($('.speeds p.active')).toHaveHtml '0.75x'
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
index 04ca674f751de954dabd375dde3ec0c326e1529f..41ac5dd3e401943cee6efebc46f33f5e2e687dfb 100644
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
@@ -1,94 +1,95 @@
-#describe 'VideoVolumeControl', ->
-#  beforeEach ->
-#    jasmine.stubVideoPlayer @
-#    $('.volume').remove()
-#
-#  describe 'constructor', ->
-#    beforeEach ->
-#      spyOn($.fn, 'slider')
-#      @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
-#
-#    it 'initialize currentVolume to 100', ->
-#      expect(@volumeControl.currentVolume).toEqual 100
-#
-#    it 'render the volume control', ->
-#      expect($('.secondary-controls').html()).toContain """
-#        <div class="volume">
-#          <a href="#"></a>
-#          <div class="volume-slider-container">
-#            <div class="volume-slider"></div>
-#          </div>
-#        </div>
-#      """
-#
-#    it 'create the slider', ->
-#      expect($.fn.slider).toHaveBeenCalledWith
-#        orientation: "vertical"
-#        range: "min"
-#        min: 0
-#        max: 100
-#        value: 100
-#        change: @volumeControl.onChange
-#        slide: @volumeControl.onChange
-#
-#    it 'bind the volume control', ->
-#      expect($('.volume>a')).toHandleWith 'click', @volumeControl.toggleMute
-#
-#      expect($('.volume')).not.toHaveClass 'open'
-#      $('.volume').mouseenter()
-#      expect($('.volume')).toHaveClass 'open'
-#      $('.volume').mouseleave()
-#      expect($('.volume')).not.toHaveClass 'open'
-#
-#  describe 'onChange', ->
-#    beforeEach ->
-#      spyOnEvent @volumeControl, 'volumeChange'
-#      @newVolume = undefined
-#      @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
-#      $(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
-#
-#    describe 'when the new volume is more than 0', ->
-#      beforeEach ->
-#        @volumeControl.onChange undefined, value: 60
-#
-#      it 'set the player volume', ->
-#        expect(@newVolume).toEqual 60
-#
-#      it 'remote muted class', ->
-#        expect($('.volume')).not.toHaveClass 'muted'
-#
-#    describe 'when the new volume is 0', ->
-#      beforeEach ->
-#        @volumeControl.onChange undefined, value: 0
-#
-#      it 'set the player volume', ->
-#        expect(@newVolume).toEqual 0
-#
-#      it 'add muted class', ->
-#        expect($('.volume')).toHaveClass 'muted'
-#
-#  describe 'toggleMute', ->
-#    beforeEach ->
-#      @newVolume = undefined
-#      @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
-#      $(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
-#
-#    describe 'when the current volume is more than 0', ->
-#      beforeEach ->
-#        @volumeControl.currentVolume = 60
-#        @volumeControl.toggleMute()
-#
-#      it 'save the previous volume', ->
-#        expect(@volumeControl.previousVolume).toEqual 60
-#
-#      it 'set the player volume', ->
-#        expect(@newVolume).toEqual 0
-#
-#    describe 'when the current volume is 0', ->
-#      beforeEach ->
-#        @volumeControl.currentVolume = 0
-#        @volumeControl.previousVolume = 60
-#        @volumeControl.toggleMute()
-#
-#      it 'set the player volume to previous volume', ->
-#        expect(@newVolume).toEqual 60
+# TODO: figure out why failing
+xdescribe 'VideoVolumeControl', ->
+  beforeEach ->
+    jasmine.stubVideoPlayer @
+    $('.volume').remove()
+
+  describe 'constructor', ->
+    beforeEach ->
+      spyOn($.fn, 'slider')
+      @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
+
+    it 'initialize currentVolume to 100', ->
+      expect(@volumeControl.currentVolume).toEqual 100
+
+    it 'render the volume control', ->
+      expect($('.secondary-controls').html()).toContain """
+        <div class="volume">
+          <a href="#"></a>
+          <div class="volume-slider-container">
+            <div class="volume-slider"></div>
+          </div>
+        </div>
+      """
+
+    it 'create the slider', ->
+      expect($.fn.slider).toHaveBeenCalledWith
+        orientation: "vertical"
+        range: "min"
+        min: 0
+        max: 100
+        value: 100
+        change: @volumeControl.onChange
+        slide: @volumeControl.onChange
+
+    it 'bind the volume control', ->
+      expect($('.volume>a')).toHandleWith 'click', @volumeControl.toggleMute
+
+      expect($('.volume')).not.toHaveClass 'open'
+      $('.volume').mouseenter()
+      expect($('.volume')).toHaveClass 'open'
+      $('.volume').mouseleave()
+      expect($('.volume')).not.toHaveClass 'open'
+
+  describe 'onChange', ->
+    beforeEach ->
+      spyOnEvent @volumeControl, 'volumeChange'
+      @newVolume = undefined
+      @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
+      $(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
+
+    describe 'when the new volume is more than 0', ->
+      beforeEach ->
+        @volumeControl.onChange undefined, value: 60
+
+      it 'set the player volume', ->
+        expect(@newVolume).toEqual 60
+
+      it 'remote muted class', ->
+        expect($('.volume')).not.toHaveClass 'muted'
+
+    describe 'when the new volume is 0', ->
+      beforeEach ->
+        @volumeControl.onChange undefined, value: 0
+
+      it 'set the player volume', ->
+        expect(@newVolume).toEqual 0
+
+      it 'add muted class', ->
+        expect($('.volume')).toHaveClass 'muted'
+
+  describe 'toggleMute', ->
+    beforeEach ->
+      @newVolume = undefined
+      @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
+      $(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
+
+    describe 'when the current volume is more than 0', ->
+      beforeEach ->
+        @volumeControl.currentVolume = 60
+        @volumeControl.toggleMute()
+
+      it 'save the previous volume', ->
+        expect(@volumeControl.previousVolume).toEqual 60
+
+      it 'set the player volume', ->
+        expect(@newVolume).toEqual 0
+
+    describe 'when the current volume is 0', ->
+      beforeEach ->
+        @volumeControl.currentVolume = 0
+        @volumeControl.previousVolume = 60
+        @volumeControl.toggleMute()
+
+      it 'set the player volume to previous volume', ->
+        expect(@newVolume).toEqual 60