(function (root, factory) { define(["mock", "converse-api", "test_utils"], factory); } (this, function (mock, converse, test_utils) { var _ = converse.env._; var $ = converse.env.jQuery; var $pres = converse.env.$pres; var $iq = converse.env.$iq; var checkHeaderToggling = function ($header) { var $toggle = $header.find('a.group-toggle'); expect($header.css('display')).toEqual('block'); expect($header.nextUntil('dt', 'dd').length === $header.nextUntil('dt', 'dd:visible').length).toBeTruthy(); expect($toggle.hasClass('icon-closed')).toBeFalsy(); expect($toggle.hasClass('icon-opened')).toBeTruthy(); $toggle.click(); expect($toggle.hasClass('icon-closed')).toBeTruthy(); expect($toggle.hasClass('icon-opened')).toBeFalsy(); expect($header.nextUntil('dt', 'dd').length === $header.nextUntil('dt', 'dd:hidden').length).toBeTruthy(); $toggle.click(); expect($toggle.hasClass('icon-closed')).toBeFalsy(); expect($toggle.hasClass('icon-opened')).toBeTruthy(); expect($header.nextUntil('dt', 'dd').length === $header.nextUntil('dt', 'dd:visible').length).toBeTruthy(); }; describe("The Control Box", function () { it("can be opened by clicking a DOM element with class 'toggle-controlbox'", mock.initConverse(function (_converse) { runs(function () { // This spec will only pass if the controlbox is not currently // open yet. expect($("div#controlbox").is(':visible')).toBe(false); spyOn(_converse.controlboxtoggle, 'onClick').andCallThrough(); spyOn(_converse.controlboxtoggle, 'showControlBox').andCallThrough(); spyOn(_converse, 'emit'); // Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick') _converse.controlboxtoggle.delegateEvents(); $('.toggle-controlbox').click(); }.bind(_converse)); waits(50); runs(function () { expect(_converse.controlboxtoggle.onClick).toHaveBeenCalled(); expect(_converse.controlboxtoggle.showControlBox).toHaveBeenCalled(); expect(_converse.emit).toHaveBeenCalledWith('controlBoxOpened', jasmine.any(Object)); expect($("div#controlbox").is(':visible')).toBe(true); }.bind(_converse)); })); describe("The Status Widget", function () { it("shows the user's chat status, which is online by default", mock.initConverse(function (_converse) { test_utils.openControlBox(); var view = _converse.xmppstatusview; expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true); expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am online'); })); it("can be used to set the current user's chat status", mock.initConverse(function (_converse) { test_utils.openControlBox(); var view = _converse.xmppstatusview; spyOn(view, 'toggleOptions').andCallThrough(); spyOn(view, 'setStatus').andCallThrough(); spyOn(_converse, 'emit'); view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called runs(function () { view.$el.find('a.choose-xmpp-status').click(); expect(view.toggleOptions).toHaveBeenCalled(); }); waits(250); runs(function () { spyOn(view, 'updateStatusUI').andCallThrough(); view.initialize(); // Rebind events for spy $(view.$el.find('.dropdown dd ul li a')[1]).click(); // Change status to "dnd" expect(view.setStatus).toHaveBeenCalled(); expect(_converse.emit).toHaveBeenCalledWith('statusChanged', 'dnd'); }); waits(250); runs(function () { expect(view.updateStatusUI).toHaveBeenCalled(); expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(false); expect(view.$el.find('a.choose-xmpp-status').hasClass('dnd')).toBe(true); expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am busy'); }); })); it("can be used to set a custom status message", mock.initConverse(function (_converse) { test_utils.openControlBox(); var view = _converse.xmppstatusview; _converse.xmppstatus.save({'status': 'online'}); spyOn(view, 'setStatusMessage').andCallThrough(); spyOn(view, 'renderStatusChangeForm').andCallThrough(); spyOn(_converse, 'emit'); view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called view.$el.find('a.change-xmpp-status-message').click(); expect(view.renderStatusChangeForm).toHaveBeenCalled(); // The async testing here is used only to provide time for // visual feedback var msg = 'I am happy'; runs (function () { view.$el.find('form input.custom-xmpp-status').val(msg); }); waits(250); runs (function () { view.$el.find('form#set-custom-xmpp-status').submit(); expect(view.setStatusMessage).toHaveBeenCalled(); expect(_converse.emit).toHaveBeenCalledWith('statusMessageChanged', msg); expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true); expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe(msg); }); })); }); }); describe("The Contacts Roster", function () { describe("The live filter", function () { it("will only appear when roster contacts flow over the visible area", mock.initConverse(function (_converse) { var $filter = _converse.rosterview.$('.roster-filter'); var names = mock.cur_names; runs(function () { test_utils.openControlBox(); _converse.rosterview.update(); // XXX: Will normally called as event handler }); waits(5); // Needed, due to debounce runs(function () { expect($filter.length).toBe(1); expect($filter.is(':visible')).toBeFalsy(); for (var i=0; i