(function() { 'use strict'; describe('XBlockToXModuleShim', function() { describe('definition', function() { it('XBlockToXModuleShim is defined, and is a function', function() { expect($.isFunction(XBlockToXModuleShim)).toBe(true); }); }); describe('implementation', function() { var $el, videoModule = { module: 'video_module' }, editCallback, displayCallback, removeNone, removeVideo; beforeEach(function() { $el = $('
'); if (window.None) { spyOn(window, 'None'); removeNone = false; } else { window.None = jasmine.createSpy('None'); removeNone = true; } if (window.Video) { spyOn(window, 'Video'); removeVideo = false; } else { window.Video = jasmine.createSpy('Video'); removeVideo = true; } window.Video.and.returnValue(videoModule); editCallback = jasmine.createSpy('editCallback'); $(document).on('XModule.loaded.edit', editCallback); spyOnEvent($(document), 'XModule.loaded.edit'); displayCallback = jasmine.createSpy('displayCallback'); $(document).on('XModule.loaded.display', displayCallback); spyOnEvent($(document), 'XModule.loaded.display'); }); afterEach(function() { $el = null; if (removeNone) { window.None = undefined; } if (removeVideo) { window.Video = undefined; } }); it('if element module is of type None, nothing happens', function() { $el.data('type', 'None'); expect(XBlockToXModuleShim(null, $el)).toBeUndefined(); expect(window.None).not.toHaveBeenCalled(); }); it('if element module is of type Video, Video module constructor is called', function() { $el.data('type', 'Video'); expect(XBlockToXModuleShim(null, $el)).toEqual(videoModule); expect(window.Video).toHaveBeenCalled(); expect('XModule.loaded.edit').not.toHaveBeenTriggeredOn(document); expect('XModule.loaded.display').not.toHaveBeenTriggeredOn(document); }); it('if element has class "xmodule_edit"', function() { $el.data('type', 'Video') .addClass('xmodule_edit'); XBlockToXModuleShim(null, $el); expect('XModule.loaded.edit').toHaveBeenTriggeredOn($(document)); expect(editCallback).toHaveBeenCalledWith(jasmine.any($.Event), $el, videoModule); expect('XModule.loaded.display').not.toHaveBeenTriggeredOn($(document)); }); it('if element has class "xmodule_display"', function() { $el.data('type', 'Video') .addClass('xmodule_display'); XBlockToXModuleShim(null, $el); expect('XModule.loaded.edit').not.toHaveBeenTriggeredOn($(document)); expect('XModule.loaded.display').toHaveBeenTriggeredOn($(document)); expect(displayCallback).toHaveBeenCalledWith(jasmine.any($.Event), $el, videoModule); }); it('if element has classes "xmodule_edit", and "xmodule_display"', function() { $el.data('type', 'Video') .addClass('xmodule_edit') .addClass('xmodule_display'); XBlockToXModuleShim(null, $el); expect('XModule.loaded.edit').toHaveBeenTriggeredOn($(document)); expect('XModule.loaded.display').toHaveBeenTriggeredOn($(document)); }); it('element is of an unknown Module type, console.error() is called if it is defined', function() { var oldConsole = window.console; if (window.console && window.console.error) { spyOn(window.console, 'error'); } else { window.console = jasmine.createSpy('console.error'); } $el.data('type', 'UnknownModule'); expect(XBlockToXModuleShim(null, $el)).toBeUndefined(); expect(console.error).toHaveBeenCalledWith( 'Unable to load UnknownModule: window[moduleType] is not a constructor' ); window.console = oldConsole; }); it('element is of an unknown Module type, JavaScript throws if console.error() is not defined', function() { var oldConsole = window.console, testFunction = function() { return XBlockToXModuleShim(null, $el); }; if (window.console) { window.console = undefined; } $el.data('type', 'UnknownModule'); expect(testFunction).toThrow(); window.console = oldConsole; }); }); }); describe('XModule.Descriptor', function() { describe('definition', function() { it('XModule is defined, and is a plain object', function() { expect($.isPlainObject(XModule)).toBe(true); }); it('XModule.Descriptor is defined, and is a function', function() { expect($.isFunction(XModule.Descriptor)).toBe(true); }); it('XModule.Descriptor has a complete prototype', function() { expect($.isFunction(XModule.Descriptor.prototype.onUpdate)).toBe(true); expect($.isFunction(XModule.Descriptor.prototype.update)).toBe(true); expect($.isFunction(XModule.Descriptor.prototype.save)).toBe(true); }); }); describe('implementation', function() { var el, obj, callback, length; // This is a dummy callback. callback = function() { var x = 1; return x + 1; }; beforeEach(function() { el = 'dummy object'; obj = new XModule.Descriptor(el); spyOn(obj, 'save').and.callThrough(); }); afterEach(function() { el = null; obj = null; length = undefined; }); it('Descriptor is a proper constructor function', function() { expect(obj.hasOwnProperty('element')).toBe(true); expect(obj.element).toBe(el); expect(obj.hasOwnProperty('update')).toBe(true); }); it('Descriptor.onUpdate called for the first time', function() { expect(obj.hasOwnProperty('callbacks')).toBe(false); obj.onUpdate(callback); expect(obj.hasOwnProperty('callbacks')).toBe(true); expect($.isArray(obj.callbacks)).toBe(true); length = obj.callbacks.length; expect(length).toBe(1); expect(obj.callbacks[length - 1]).toBe(callback); }); it('Descriptor.onUpdate called for Nth time', function() { // In this test it doesn't matter what obj.callbacks // consists of. obj.callbacks = ['test1', 'test2', 'test3']; obj.onUpdate(callback); length = obj.callbacks.length; expect(length).toBe(4); expect(obj.callbacks[length - 1]).toBe(callback); }); it('Descriptor.save returns a blank object', function() { // NOTE: In the future the implementation of .save() // method may change! expect(obj.save()).toEqual({}); }); it('Descriptor.update triggers all callbacks with whatever .save() returns', function() { var callback1 = jasmine.createSpy('callback1'), callback2 = jasmine.createSpy('callback2'), testValue = 'test 123'; obj.onUpdate(callback1); obj.onUpdate(callback2); obj.save.and.returnValue(testValue); obj.update(); expect(callback1).toHaveBeenCalledWith(testValue); expect(callback2).toHaveBeenCalledWith(testValue); }); }); }); }).call(this);