Commit 0c43e4b8 authored by JC Brand's avatar JC Brand

Upgrade to Jasmine 2.5.3

parent bf9ba245
...@@ -255,7 +255,7 @@ ...@@ -255,7 +255,7 @@
"error", "error",
"never" "never"
], ],
"valid-jsdoc": "error", "valid-jsdoc": "off",
"vars-on-top": "off", "vars-on-top": "off",
"wrap-iife": [ "wrap-iife": [
"error", "error",
......
...@@ -3,7 +3,6 @@ BUILDDIR = ./docs ...@@ -3,7 +3,6 @@ BUILDDIR = ./docs
BUNDLE ?= ./.bundle/bin/bundle BUNDLE ?= ./.bundle/bin/bundle
GRUNT ?= ./node_modules/.bin/grunt GRUNT ?= ./node_modules/.bin/grunt
HTTPSERVE ?= ./node_modules/.bin/http-server HTTPSERVE ?= ./node_modules/.bin/http-server
JSHINT ?= ./node_modules/.bin/jshint
ESLINT ?= ./node_modules/.bin/eslint ESLINT ?= ./node_modules/.bin/eslint
PAPER = PAPER =
PHANTOMJS ?= ./node_modules/.bin/phantomjs PHANTOMJS ?= ./node_modules/.bin/phantomjs
...@@ -16,13 +15,6 @@ SPHINXOPTS = ...@@ -16,13 +15,6 @@ SPHINXOPTS =
# Internal variables. # Internal variables.
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source
SOURCES = $(wildcard *.js) $(wildcard spec/*.js) $(wildcard src/*.js)
JSHINTEXCEPTIONS = $(GENERATED) \
src/build-mobile.js \
src/build-no-jquery.js \
src/build-no-dependencies.js \
src/build.js \
CHECKSOURCES = $(filter-out $(JSHINTEXCEPTIONS),$(SOURCES))
.PHONY: all .PHONY: all
all: dev dist all: dev dist
...@@ -184,18 +176,15 @@ build:: dev css ...@@ -184,18 +176,15 @@ build:: dev css
######################################################################## ########################################################################
## Tests ## Tests
.PHONY: jshint
jshint: stamp-npm
$(JSHINT) --config jshintrc $(CHECKSOURCES)
.PHONY: eslint .PHONY: eslint
eslint: stamp-npm eslint: stamp-npm
$(ESLINT) src/ $(ESLINT) src/
$(ESLINT) spec/ $(ESLINT) spec/
.PHONY: check .PHONY: check
check: jshint eslint check: eslint
$(PHANTOMJS) node_modules/phantom-jasmine/lib/run_jasmine_test.coffee tests.html $(PHANTOMJS) tests/run-jasmine2.js tests.html
######################################################################## ########################################################################
## Documentation ## Documentation
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
## 3.0.2 (Unreleased) ## 3.0.2 (Unreleased)
- No changes yet. - Update Jasmine from 1.3.1 to 2.5.3 and Phantomjs from 1.9.7-1 to 2.1.14 [jcbrand]
## 3.0.1 (2017-04-04) ## 3.0.1 (2017-04-04)
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
"bootstrap": "^3.3.7", "bootstrap": "^3.3.7",
"bourbon": "^4.3.2", "bourbon": "^4.3.2",
"clean-css": "^3.4.19", "clean-css": "^3.4.19",
"es6-promise": "^4.1.0",
"eslint": "^3.16.1", "eslint": "^3.16.1",
"eslint-plugin-lodash": "^2.3.3", "eslint-plugin-lodash": "^2.3.3",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
...@@ -49,7 +50,7 @@ ...@@ -49,7 +50,7 @@
"grunt-json": "^0.2.0", "grunt-json": "^0.2.0",
"http-server": "^0.9.0", "http-server": "^0.9.0",
"install": "^0.8.5", "install": "^0.8.5",
"jasmine": "https://github.com/jcbrand/jasmine.git#439a7f805eeaec0cabe18a8ecf7e47da1a0afa33", "jasmine": "2.5.3",
"jed": "0.5.4", "jed": "0.5.4",
"jquery": "2.2.3", "jquery": "2.2.3",
"jquery-easing": "0.0.1", "jquery-easing": "0.0.1",
...@@ -60,8 +61,7 @@ ...@@ -60,8 +61,7 @@
"moment": "~2.13.0", "moment": "~2.13.0",
"npm": "^4.1.1", "npm": "^4.1.1",
"otr": "0.2.16", "otr": "0.2.16",
"phantom-jasmine": "0.1.8", "phantomjs-prebuilt": "~2.1.14",
"phantomjs": "~1.9.7-1",
"pluggable.js": "1.0.0", "pluggable.js": "1.0.0",
"po2json": "^0.4.4", "po2json": "^0.4.4",
"requirejs": "2.3.3", "requirejs": "2.3.3",
...@@ -73,7 +73,8 @@ ...@@ -73,7 +73,8 @@
"strophejs-plugin-register": "0.0.1", "strophejs-plugin-register": "0.0.1",
"strophejs-plugin-rsm": "0.0.1", "strophejs-plugin-rsm": "0.0.1",
"strophejs-plugin-vcard": "0.0.1", "strophejs-plugin-vcard": "0.0.1",
"text": "requirejs/text#2.0.15" "text": "requirejs/text#2.0.15",
"wait-until-promise": "^1.0.0"
}, },
"dependencies": {} "dependencies": {}
} }
/*global waitUntilPromise */
(function (root, factory) { (function (root, factory) {
define([ define([
"jquery", "jquery",
"converse-core", "converse-core",
"utils", "utils",
"mock", "mock",
"test_utils" "test-utils"
], factory); ], factory);
} (this, function ($, converse, utils, mock, test_utils) { } (this, function ($, converse, utils, mock, test_utils) {
"use strict"; "use strict";
...@@ -17,17 +19,17 @@ ...@@ -17,17 +19,17 @@
it("can be bookmarked", mock.initConverse(function (_converse) { it("can be bookmarked", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
spyOn(_converse.connection, 'getUniqueId').andCallThrough(); spyOn(_converse.connection, 'getUniqueId').and.callThrough();
test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC'); test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC');
var jid = 'theplay@conference.shakespeare.lit'; var jid = 'theplay@conference.shakespeare.lit';
var view = _converse.chatboxviews.get(jid); var view = _converse.chatboxviews.get(jid);
spyOn(view, 'renderBookmarkForm').andCallThrough(); spyOn(view, 'renderBookmarkForm').and.callThrough();
spyOn(view, 'cancelConfiguration').andCallThrough(); spyOn(view, 'cancelConfiguration').and.callThrough();
var $bookmark = view.$el.find('.icon-pushpin'); var $bookmark = view.$el.find('.icon-pushpin');
$bookmark.click(); $bookmark.click();
...@@ -146,85 +148,73 @@ ...@@ -146,85 +148,73 @@
describe("when bookmarked", function () { describe("when bookmarked", function () {
it("displays that it's bookmarked through its bookmark icon", mock.initConverse(function (_converse) { it("displays that it's bookmarked through its bookmark icon", mock.initConverse(function (_converse) {
runs(function () { test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); var view = _converse.chatboxviews.get('lounge@localhost');
}); var $bookmark_icon = view.$('.icon-pushpin');
waits(100); expect($bookmark_icon.hasClass('button-on')).toBeFalsy();
runs(function () { view.model.set('bookmarked', true);
var view = _converse.chatboxviews.get('lounge@localhost'); expect($bookmark_icon.hasClass('button-on')).toBeTruthy();
var $bookmark_icon = view.$('.icon-pushpin'); view.model.set('bookmarked', false);
expect($bookmark_icon.hasClass('button-on')).toBeFalsy(); expect($bookmark_icon.hasClass('button-on')).toBeFalsy();
view.model.set('bookmarked', true);
expect($bookmark_icon.hasClass('button-on')).toBeTruthy();
view.model.set('bookmarked', false);
expect($bookmark_icon.hasClass('button-on')).toBeFalsy();
});
})); }));
it("can be unbookmarked", mock.initConverse(function (_converse) { it("can be unbookmarked", mock.initConverse(function (_converse) {
var view, sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC');
var jid = 'theplay@conference.shakespeare.lit';
var view = _converse.chatboxviews.get(jid);
spyOn(view, 'toggleBookmark').and.callThrough();
spyOn(_converse.bookmarks, 'sendBookmarkStanza').and.callThrough();
view.delegateEvents();
_converse.bookmarks.create({
'jid': view.model.get('jid'),
'autojoin': false,
'name': 'The Play',
'nick': ' Othello'
});
expect(_converse.bookmarks.length).toBe(1);
expect(view.model.get('bookmarked')).toBeTruthy();
var $bookmark_icon = view.$('.icon-pushpin');
expect($bookmark_icon.hasClass('button-on')).toBeTruthy();
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
spyOn(_converse.connection, 'getUniqueId').andCallThrough(); spyOn(_converse.connection, 'getUniqueId').and.callThrough();
$bookmark_icon.click();
expect(view.toggleBookmark).toHaveBeenCalled();
expect($bookmark_icon.hasClass('button-on')).toBeFalsy();
expect(_converse.bookmarks.length).toBe(0);
runs(function () { // Check that an IQ stanza is sent out, containing no
test_utils.openChatRoom(_converse, 'theplay', 'conference.shakespeare.lit', 'JC'); // conferences to bookmark (since we removed the one and
}); // only bookmark).
waits(100); expect(sent_stanza.toLocaleString()).toBe(
runs(function () { "<iq type='set' from='dummy@localhost/resource' xmlns='jabber:client' id='"+IQ_id+"'>"+
var jid = 'theplay@conference.shakespeare.lit'; "<pubsub xmlns='http://jabber.org/protocol/pubsub'>"+
view = _converse.chatboxviews.get(jid); "<publish node='storage:bookmarks'>"+
spyOn(view, 'toggleBookmark').andCallThrough(); "<item id='current'>"+
spyOn(_converse.bookmarks, 'sendBookmarkStanza').andCallThrough(); "<storage xmlns='storage:bookmarks'/>"+
view.delegateEvents(); "</item>"+
_converse.bookmarks.create({ "</publish>"+
'jid': view.model.get('jid'), "<publish-options>"+
'autojoin': false, "<x xmlns='jabber:x:data' type='submit'>"+
'name': 'The Play', "<field var='FORM_TYPE' type='hidden'>"+
'nick': ' Othello' "<value>http://jabber.org/protocol/pubsub#publish-options</value>"+
}); "</field>"+
expect(_converse.bookmarks.length).toBe(1); "<field var='pubsub#persist_items'>"+
}); "<value>true</value>"+
waits(100); "</field>"+
runs(function () { "<field var='pubsub#access_model'>"+
expect(view.model.get('bookmarked')).toBeTruthy(); "<value>whitelist</value>"+
var $bookmark_icon = view.$('.icon-pushpin'); "</field>"+
expect($bookmark_icon.hasClass('button-on')).toBeTruthy(); "</x>"+
$bookmark_icon.click(); "</publish-options>"+
expect(view.toggleBookmark).toHaveBeenCalled(); "</pubsub>"+
expect($bookmark_icon.hasClass('button-on')).toBeFalsy(); "</iq>"
expect(_converse.bookmarks.length).toBe(0); );
// Check that an IQ stanza is sent out, containing no
// conferences to bookmark (since we removed the one and
// only bookmark).
expect(sent_stanza.toLocaleString()).toBe(
"<iq type='set' from='dummy@localhost/resource' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<pubsub xmlns='http://jabber.org/protocol/pubsub'>"+
"<publish node='storage:bookmarks'>"+
"<item id='current'>"+
"<storage xmlns='storage:bookmarks'/>"+
"</item>"+
"</publish>"+
"<publish-options>"+
"<x xmlns='jabber:x:data' type='submit'>"+
"<field var='FORM_TYPE' type='hidden'>"+
"<value>http://jabber.org/protocol/pubsub#publish-options</value>"+
"</field>"+
"<field var='pubsub#persist_items'>"+
"<value>true</value>"+
"</field>"+
"<field var='pubsub#access_model'>"+
"<value>whitelist</value>"+
"</field>"+
"</x>"+
"</publish-options>"+
"</pubsub>"+
"</iq>"
);
});
})); }));
}); });
...@@ -255,7 +245,7 @@ ...@@ -255,7 +245,7 @@
describe("Bookmarks", function () { describe("Bookmarks", function () {
it("can be pushed from the XMPP server", mock.initConverse(function (_converse) { xit("can be pushed from the XMPP server", mock.initConverse(function (_converse) {
// TODO // TODO
/* The stored data is automatically pushed to all of the user's /* The stored data is automatically pushed to all of the user's
* connected resources. * connected resources.
...@@ -305,7 +295,7 @@ ...@@ -305,7 +295,7 @@
it("can be retrieved from the XMPP server", mock.initConverse(function (_converse) { it("can be retrieved from the XMPP server", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id, var sent_stanza, IQ_id,
sendIQ = _converse.connection.sendIQ; sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -376,7 +366,7 @@ ...@@ -376,7 +366,7 @@
it("shows a list of bookmarks", mock.initConverse(function (_converse) { it("shows a list of bookmarks", mock.initConverse(function (_converse) {
var IQ_id; var IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
_converse.chatboxviews.get('controlbox').$('#chatrooms dl.bookmarks').html(''); _converse.chatboxviews.get('controlbox').$('#chatrooms dl.bookmarks').html('');
...@@ -406,27 +396,22 @@ ...@@ -406,27 +396,22 @@
})); }));
it("remembers the toggle state of the bookmarks list", mock.initConverse(function (_converse) { it("remembers the toggle state of the bookmarks list", mock.initConverse(function (_converse) {
runs(function () { _converse.bookmarks.create({
_converse.bookmarks.create({ 'jid': 'theplay@conference.shakespeare.lit',
'jid': 'theplay@conference.shakespeare.lit', 'autojoin': false,
'autojoin': false, 'name': 'The Play',
'name': 'The Play', 'nick': ''
'nick': ''
});
_converse.emit('chatBoxesFetched');
test_utils.openControlBox().openRoomsPanel(_converse);
});
waits(100);
runs(function () {
expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1);
expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED);
$('#chatrooms .bookmarks-toggle').click();
expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(0);
expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.CLOSED);
$('#chatrooms .bookmarks-toggle').click();
expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1);
expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED);
}); });
_converse.emit('chatBoxesFetched');
test_utils.openControlBox().openRoomsPanel(_converse);
expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1);
expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED);
$('#chatrooms .bookmarks-toggle').click();
expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(0);
expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.CLOSED);
$('#chatrooms .bookmarks-toggle').click();
expect($('#chatrooms dl.bookmarks dd:visible').length).toBe(1);
expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED);
})); }));
}); });
}); });
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"utils", "utils",
"converse-core", "converse-core",
"mock", "mock",
"test_utils" "test-utils"
], factory); ], factory);
} (this, function (utils, converse, mock, test_utils) { } (this, function (utils, converse, mock, test_utils) {
"use strict"; "use strict";
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
} }
})); }));
it("can be trimmed to conserve space", mock.initConverse(function (_converse) { it("can be trimmed to conserve space", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
...@@ -80,16 +80,15 @@ ...@@ -80,16 +80,15 @@
var trimmed_chatboxes = _converse.minimized_chats; var trimmed_chatboxes = _converse.minimized_chats;
expect(_converse.chatboxes.length).toEqual(1); expect(_converse.chatboxes.length).toEqual(1);
spyOn(_converse.chatboxviews, 'trimChats'); spyOn(_converse.chatboxviews, 'trimChats');
spyOn(trimmed_chatboxes, 'addChat').andCallThrough(); spyOn(trimmed_chatboxes, 'addChat').and.callThrough();
spyOn(trimmed_chatboxes, 'removeChat').andCallThrough(); spyOn(trimmed_chatboxes, 'removeChat').and.callThrough();
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
// Test that they can be trimmed _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
runs(function () { test_utils.waitUntil(function () {
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced. return _converse.rosterview.$el.find('dt').length;
}); }, 300)
waits(50); .then(function () {
runs(function () {
// Test that they can be maximized again // Test that they can be maximized again
var online_contacts = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact').find('a.open-chat'); var online_contacts = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact').find('a.open-chat');
for (i=0; i<online_contacts.length; i++) { for (i=0; i<online_contacts.length; i++) {
...@@ -99,29 +98,31 @@ ...@@ -99,29 +98,31 @@
expect(_converse.chatboxviews.trimChats).toHaveBeenCalled(); expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
chatboxview = _converse.chatboxviews.get(jid); chatboxview = _converse.chatboxviews.get(jid);
spyOn(chatboxview, 'minimize').andCallThrough(); spyOn(chatboxview, 'minimize').and.callThrough();
chatboxview.model.set({'minimized': true}); chatboxview.model.set({'minimized': true});
expect(trimmed_chatboxes.addChat).toHaveBeenCalled(); expect(trimmed_chatboxes.addChat).toHaveBeenCalled();
expect(chatboxview.minimize).toHaveBeenCalled(); expect(chatboxview.minimize).toHaveBeenCalled();
trimmedview = trimmed_chatboxes.get(jid);
} }
return test_utils.waitUntil(function () {
return _converse.chatboxviews.keys().length > 1;
}, 500)
}).then(function () {
var key = _converse.chatboxviews.keys()[1]; var key = _converse.chatboxviews.keys()[1];
trimmedview = trimmed_chatboxes.get(key); trimmedview = trimmed_chatboxes.get(key);
chatbox = trimmedview.model; chatbox = trimmedview.model;
spyOn(chatbox, 'maximize').andCallThrough(); spyOn(chatbox, 'maximize').and.callThrough();
spyOn(trimmedview, 'restore').andCallThrough(); spyOn(trimmedview, 'restore').and.callThrough();
trimmedview.delegateEvents(); trimmedview.delegateEvents();
trimmedview.$("a.restore-chat").click(); trimmedview.$("a.restore-chat").click();
});
waits(250);
runs(function () {
expect(trimmedview.restore).toHaveBeenCalled(); expect(trimmedview.restore).toHaveBeenCalled();
expect(chatbox.maximize).toHaveBeenCalled(); expect(chatbox.maximize).toHaveBeenCalled();
expect(_converse.chatboxviews.trimChats).toHaveBeenCalled(); expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
done();
}); });
})); }));
it("is focused if its already open and you click on its corresponding roster item", mock.initConverse(function (_converse) { it("is focused if its already open and you click on its corresponding roster item", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
...@@ -135,16 +136,19 @@ ...@@ -135,16 +136,19 @@
chatboxview = _converse.chatboxviews.get(contact_jid); chatboxview = _converse.chatboxviews.get(contact_jid);
spyOn(chatboxview, 'focus'); spyOn(chatboxview, 'focus');
// Test that they can be trimmed // Test that they can be trimmed
runs(function () { _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced. test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(300); // ChatBox.show() is debounced for 250ms }, 300)
runs(function () { .then(function () {
$el = _converse.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")'); $el = _converse.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")');
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost'; jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
$el.click(); $el.click();
expect(_converse.chatboxes.length).toEqual(2); setTimeout(function () {
expect(chatboxview.focus).toHaveBeenCalled(); expect(_converse.chatboxes.length).toEqual(2);
expect(chatboxview.focus).toHaveBeenCalled();
done();
}, 500);
}); });
})); }));
...@@ -155,122 +159,121 @@ ...@@ -155,122 +159,121 @@
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.chatboxviews, 'trimChats'); spyOn(_converse.chatboxviews, 'trimChats');
runs(function () { test_utils.openControlBox();
test_utils.openControlBox();
}); test_utils.openChatBoxes(_converse, 6);
waits(250); expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
runs(function () { // We instantiate a new ChatBoxes collection, which by default
test_utils.openChatBoxes(_converse, 6); // will be empty.
expect(_converse.chatboxviews.trimChats).toHaveBeenCalled(); var newchatboxes = new _converse.ChatBoxes();
// We instantiate a new ChatBoxes collection, which by default expect(newchatboxes.length).toEqual(0);
// will be empty. // The chatboxes will then be fetched from browserStorage inside the
var newchatboxes = new _converse.ChatBoxes(); // onConnected method
expect(newchatboxes.length).toEqual(0); newchatboxes.onConnected();
// The chatboxes will then be fetched from browserStorage inside the expect(newchatboxes.length).toEqual(7);
// onConnected method // Check that the chatboxes items retrieved from browserStorage
newchatboxes.onConnected(); // have the same attributes values as the original ones.
expect(newchatboxes.length).toEqual(7); var attrs = ['id', 'box_id', 'visible'];
// Check that the chatboxes items retrieved from browserStorage var new_attrs, old_attrs;
// have the same attributes values as the original ones. for (var i=0; i<attrs.length; i++) {
var attrs = ['id', 'box_id', 'visible']; new_attrs = _.map(_.map(newchatboxes.models, 'attributes'), attrs[i]);
var new_attrs, old_attrs; old_attrs = _.map(_.map(_converse.chatboxes.models, 'attributes'), attrs[i]);
for (var i=0; i<attrs.length; i++) { expect(_.isEqual(new_attrs, old_attrs)).toEqual(true);
new_attrs = _.map(_.map(newchatboxes.models, 'attributes'), attrs[i]); }
old_attrs = _.map(_.map(_converse.chatboxes.models, 'attributes'), attrs[i]); _converse.rosterview.render();
expect(_.isEqual(new_attrs, old_attrs)).toEqual(true);
}
_converse.rosterview.render();
});
})); }));
it("can be closed by clicking a DOM element with class 'close-chatbox-button'", mock.initConverse(function (_converse) { it("can be closed by clicking a DOM element with class 'close-chatbox-button'", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 300)
.then(function () {
var chatbox = test_utils.openChatBoxes(_converse, 1)[0],
controlview = _converse.chatboxviews.get('controlbox'), // The controlbox is currently open
chatview = _converse.chatboxviews.get(chatbox.get('jid'));
spyOn(chatview, 'close').and.callThrough();
spyOn(controlview, 'close').and.callThrough();
spyOn(_converse, 'emit');
var chatbox = test_utils.openChatBoxes(_converse, 1)[0], // We need to rebind all events otherwise our spy won't be called
controlview = _converse.chatboxviews.get('controlbox'), // The controlbox is currently open controlview.delegateEvents();
chatview = _converse.chatboxviews.get(chatbox.get('jid')); chatview.delegateEvents();
spyOn(chatview, 'close').andCallThrough();
spyOn(controlview, 'close').andCallThrough();
spyOn(_converse, 'emit');
// We need to rebind all events otherwise our spy won't be called
controlview.delegateEvents();
chatview.delegateEvents();
runs(function () {
controlview.$el.find('.close-chatbox-button').click(); controlview.$el.find('.close-chatbox-button').click();
});
waits(250);
runs(function () {
expect(controlview.close).toHaveBeenCalled(); expect(controlview.close).toHaveBeenCalled();
expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
expect(_converse.emit.callCount, 1); expect(_converse.emit.calls.count(), 1);
chatview.$el.find('.close-chatbox-button').click(); chatview.$el.find('.close-chatbox-button').click();
});
waits(250);
runs(function () {
expect(chatview.close).toHaveBeenCalled(); expect(chatview.close).toHaveBeenCalled();
expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
expect(_converse.emit.callCount, 2); expect(_converse.emit.calls.count(), 2);
done();
}); });
})); }));
it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'", mock.initConverse(function (_converse) { it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'", mock.initConverseWithAsync(function (done, _converse) {
var chatview;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 300)
.then(function () {
var chatbox = test_utils.openChatBoxes(_converse, 1)[0],
trimmed_chatboxes = _converse.minimized_chats,
trimmedview;
chatview = _converse.chatboxviews.get(chatbox.get('jid'));
spyOn(chatview, 'minimize').and.callThrough();
spyOn(_converse, 'emit');
// We need to rebind all events otherwise our spy won't be called
chatview.delegateEvents();
var chatbox = test_utils.openChatBoxes(_converse, 1)[0],
chatview = _converse.chatboxviews.get(chatbox.get('jid')),
trimmed_chatboxes = _converse.minimized_chats,
trimmedview;
spyOn(chatview, 'minimize').andCallThrough();
spyOn(_converse, 'emit');
// We need to rebind all events otherwise our spy won't be called
chatview.delegateEvents();
runs(function () {
chatview.$el.find('.toggle-chatbox-button').click(); chatview.$el.find('.toggle-chatbox-button').click();
});
waits(250);
runs(function () {
expect(chatview.minimize).toHaveBeenCalled(); expect(chatview.minimize).toHaveBeenCalled();
expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object));
expect(_converse.emit.callCount, 2); expect(_converse.emit.calls.count(), 2);
expect(chatview.$el.is(':visible')).toBeFalsy(); expect(chatview.$el.is(':visible')).toBeFalsy();
expect(chatview.model.get('minimized')).toBeTruthy(); expect(chatview.model.get('minimized')).toBeTruthy();
chatview.$el.find('.toggle-chatbox-button').click(); chatview.$el.find('.toggle-chatbox-button').click();
trimmedview = trimmed_chatboxes.get(chatview.model.get('id')); trimmedview = trimmed_chatboxes.get(chatview.model.get('id'));
spyOn(trimmedview, 'restore').andCallThrough(); spyOn(trimmedview, 'restore').and.callThrough();
trimmedview.delegateEvents(); trimmedview.delegateEvents();
trimmedview.$("a.restore-chat").click(); trimmedview.$("a.restore-chat").click();
});
waits(250);
runs(function () {
expect(trimmedview.restore).toHaveBeenCalled(); expect(trimmedview.restore).toHaveBeenCalled();
expect(_converse.emit).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object));
expect(chatview.$el.find('.chat-body').is(':visible')).toBeTruthy(); return test_utils.waitUntil(function () {
return chatview.$el.find('.chat-body').is(':visible');
}, 500)
}).then(function () {
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy(); expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy();
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy(); expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy();
expect(chatview.model.get('minimized')).toBeFalsy(); expect(chatview.model.get('minimized')).toBeFalsy();
done();
}); });
})); }));
it("will be removed from browserStorage when closed", mock.initConverse(function (_converse) { it("will be removed from browserStorage when closed", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 300)
.then(function () {
spyOn(_converse, 'emit');
spyOn(_converse.chatboxviews, 'trimChats');
_converse.chatboxes.browserStorage._clear();
spyOn(_converse, 'emit');
spyOn(_converse.chatboxviews, 'trimChats');
_converse.chatboxes.browserStorage._clear();
runs(function () {
test_utils.closeControlBox(); test_utils.closeControlBox();
});
waits(50);
runs(function () {
expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
expect(_converse.chatboxes.length).toEqual(1); expect(_converse.chatboxes.length).toEqual(1);
expect(_converse.chatboxes.pluck('id')).toEqual(['controlbox']); expect(_converse.chatboxes.pluck('id')).toEqual(['controlbox']);
...@@ -279,9 +282,7 @@ ...@@ -279,9 +282,7 @@
expect(_converse.chatboxes.length).toEqual(7); expect(_converse.chatboxes.length).toEqual(7);
expect(_converse.emit).toHaveBeenCalledWith('chatBoxOpened', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxOpened', jasmine.any(Object));
test_utils.closeAllChatBoxes(_converse); test_utils.closeAllChatBoxes(_converse);
});
waits(50);
runs(function () {
expect(_converse.chatboxes.length).toEqual(1); expect(_converse.chatboxes.length).toEqual(1);
expect(_converse.chatboxes.pluck('id')).toEqual(['controlbox']); expect(_converse.chatboxes.pluck('id')).toEqual(['controlbox']);
expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
...@@ -294,6 +295,7 @@ ...@@ -294,6 +295,7 @@
newchatboxes.onConnected(); newchatboxes.onConnected();
expect(newchatboxes.length).toEqual(1); expect(newchatboxes.length).toEqual(1);
expect(newchatboxes.models[0].id).toBe("controlbox"); expect(newchatboxes.models[0].id).toBe("controlbox");
done();
}); });
})); }));
...@@ -315,28 +317,28 @@ ...@@ -315,28 +317,28 @@
expect($toolbar.children('li').length).toBe(3); expect($toolbar.children('li').length).toBe(3);
})); }));
it("contains a button for inserting emoticons", mock.initConverse(function (_converse) { it("contains a button for inserting emoticons", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost', test_utils.waitUntil(function () {
view, $toolbar, $textarea; return _converse.rosterview.$el.find('dt').length;
waits(300); // ChatBox.show() is debounced for 250ms }, 300)
runs(function () { .then(function () {
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost',
view, $toolbar, $textarea;
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
$toolbar = view.$el.find('ul.chat-toolbar'); $toolbar = view.$el.find('ul.chat-toolbar');
$textarea = view.$el.find('textarea.chat-textarea'); $textarea = view.$el.find('textarea.chat-textarea');
expect($toolbar.children('li.toggle-smiley').length).toBe(1); expect($toolbar.children('li.toggle-smiley').length).toBe(1);
// Register spies // Register spies
spyOn(view, 'toggleEmoticonMenu').andCallThrough(); spyOn(view, 'toggleEmoticonMenu').and.callThrough();
spyOn(view, 'insertEmoticon').andCallThrough(); spyOn(view, 'insertEmoticon').and.callThrough();
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
$toolbar.children('li.toggle-smiley').click(); $toolbar.children('li.toggle-smiley').click();
});
waits(250);
runs(function () {
expect(view.toggleEmoticonMenu).toHaveBeenCalled(); expect(view.toggleEmoticonMenu).toHaveBeenCalled();
var $menu = view.$el.find('.toggle-smiley ul'); var $menu = view.$el.find('.toggle-smiley ul');
var $items = $menu.children('li'); var $items = $menu.children('li');
...@@ -356,54 +358,50 @@ ...@@ -356,54 +358,50 @@
expect($($items[11]).children('a').data('emoticon')).toBe('(^.^)b'); expect($($items[11]).children('a').data('emoticon')).toBe('(^.^)b');
expect($($items[12]).children('a').data('emoticon')).toBe('<3'); expect($($items[12]).children('a').data('emoticon')).toBe('<3');
$items.first().click(); $items.first().click();
});
waits(250);
runs(function () {
expect(view.insertEmoticon).toHaveBeenCalled(); expect(view.insertEmoticon).toHaveBeenCalled();
expect($textarea.val()).toBe(':) '); expect($textarea.val()).toBe(':) ');
expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy(); expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy();
$toolbar.children('li.toggle-smiley').click(); $toolbar.children('li.toggle-smiley').click();
});
waits(250);
runs(function () {
expect(view.toggleEmoticonMenu).toHaveBeenCalled(); expect(view.toggleEmoticonMenu).toHaveBeenCalled();
expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeTruthy(); expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeTruthy();
view.$el.find('.toggle-smiley ul').children('li').last().click(); view.$el.find('.toggle-smiley ul').children('li').last().click();
});
waits(250);
runs(function () {
expect(view.insertEmoticon).toHaveBeenCalled(); expect(view.insertEmoticon).toHaveBeenCalled();
expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy(); expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy();
expect($textarea.val()).toBe(':) <3 '); expect($textarea.val()).toBe(':) <3 ');
done();
}); });
})); }));
it("contains a button for starting an encrypted chat session", mock.initConverse(function (_converse) { it("contains a button for starting an encrypted chat session", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
// TODO: More tests can be added here... test_utils.waitUntil(function () {
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; return _converse.rosterview.$el.find('dt').length;
test_utils.openChatBoxFor(_converse, contact_jid); }, 300)
var view = _converse.chatboxviews.get(contact_jid); .then(function () {
var $toolbar = view.$el.find('ul.chat-toolbar'); // TODO: More tests can be added here...
expect($toolbar.children('li.toggle-otr').length).toBe(1); var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
// Register spies test_utils.openChatBoxFor(_converse, contact_jid);
spyOn(view, 'toggleOTRMenu').andCallThrough(); var view = _converse.chatboxviews.get(contact_jid);
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called var $toolbar = view.$el.find('ul.chat-toolbar');
expect($toolbar.children('li.toggle-otr').length).toBe(1);
// Register spies
spyOn(view, 'toggleOTRMenu').and.callThrough();
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
runs(function () {
$toolbar.children('li.toggle-otr').click(); $toolbar.children('li.toggle-otr').click();
});
waits(250);
runs(function () {
expect(view.toggleOTRMenu).toHaveBeenCalled(); expect(view.toggleOTRMenu).toHaveBeenCalled();
var $menu = view.$el.find('.toggle-otr ul'); var $menu = view.$el.find('.toggle-otr ul');
expect($menu.is(':visible')).toBeTruthy(); expect($menu.is(':visible')).toBeTruthy();
expect($menu.children('li').length).toBe(2); expect($menu.children('li').length).toBe(2);
done();
}); });
})); }));
it("can contain a button for starting a call", mock.initConverse(function (_converse) { it("can contain a button for starting a call", mock.initConverse(function (_converse) {
...@@ -470,32 +468,32 @@ ...@@ -470,32 +468,32 @@
describe("A Chat Message", function () { describe("A Chat Message", function () {
describe("when received from someone else", function () { describe("when received from someone else", function () {
it("can be received which will open a chatbox and be displayed inside it", mock.initConverse(function (_converse) { it("can be received which will open a chatbox and be displayed inside it", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 300)
.then(function () {
spyOn(_converse, 'emit');
var message = 'This is a received message';
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var msg = $msg({
from: sender_jid,
to: _converse.connection.jid,
type: 'chat',
id: (new Date()).getTime()
}).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
spyOn(_converse, 'emit'); // We don't already have an open chatbox for this user
var message = 'This is a received message'; expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined();
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var msg = $msg({
from: sender_jid,
to: _converse.connection.jid,
type: 'chat',
id: (new Date()).getTime()
}).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
// We don't already have an open chatbox for this user
expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined();
runs(function () {
// onMessage is a handler for received XMPP messages // onMessage is a handler for received XMPP messages
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', msg); expect(_converse.emit).toHaveBeenCalledWith('message', msg);
});
waits(50);
runs(function () {
// Check that the chatbox and its view now exist // Check that the chatbox and its view now exist
var chatbox = _converse.chatboxes.get(sender_jid); var chatbox = _converse.chatboxes.get(sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid); var chatboxview = _converse.chatboxviews.get(sender_jid);
...@@ -514,6 +512,7 @@ ...@@ -514,6 +512,7 @@
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
var sender_txt = $chat_content.find('span.chat-msg-them').text(); var sender_txt = $chat_content.find('span.chat-msg-them').text();
expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy(); expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy();
done();
}); });
})); }));
...@@ -535,42 +534,36 @@ ...@@ -535,42 +534,36 @@
// We don't already have an open chatbox for this user // We don't already have an open chatbox for this user
expect(converse.chatboxes.get(sender_jid)).not.toBeDefined(); expect(converse.chatboxes.get(sender_jid)).not.toBeDefined();
runs(function () { // onMessage is a handler for received XMPP messages
// onMessage is a handler for received XMPP messages converse.chatboxes.onMessage(msg);
converse.chatboxes.onMessage(msg); expect(converse.emit).toHaveBeenCalledWith('message', msg);
expect(converse.emit).toHaveBeenCalledWith('message', msg);
}); var chatbox = converse.chatboxes.get(sender_jid);
waits(50); expect(chatbox).not.toBeDefined();
runs(function () {
var chatbox = converse.chatboxes.get(sender_jid); // onMessage is a handler for received XMPP messages
expect(chatbox).not.toBeDefined(); converse.allow_non_roster_messaging =true;
converse.chatboxes.onMessage(msg);
// onMessage is a handler for received XMPP messages expect(converse.emit).toHaveBeenCalledWith('message', msg);
converse.allow_non_roster_messaging =true;
converse.chatboxes.onMessage(msg); // Check that the chatbox and its view now exist
expect(converse.emit).toHaveBeenCalledWith('message', msg); chatbox = converse.chatboxes.get(sender_jid);
}); var chatboxview = converse.chatboxviews.get(sender_jid);
waits(50); expect(chatbox).toBeDefined();
runs(function () { expect(chatboxview).toBeDefined();
// Check that the chatbox and its view now exist // Check that the message was received and check the message parameters
var chatbox = converse.chatboxes.get(sender_jid); expect(chatbox.messages.length).toEqual(1);
var chatboxview = converse.chatboxviews.get(sender_jid); var msg_obj = chatbox.messages.models[0];
expect(chatbox).toBeDefined(); expect(msg_obj.get('message')).toEqual(message);
expect(chatboxview).toBeDefined(); expect(msg_obj.get('fullname')).toEqual(sender_jid);
// Check that the message was received and check the message parameters expect(msg_obj.get('sender')).toEqual('them');
expect(chatbox.messages.length).toEqual(1); expect(msg_obj.get('delayed')).toEqual(false);
var msg_obj = chatbox.messages.models[0]; // Now check that the message appears inside the chatbox in the DOM
expect(msg_obj.get('message')).toEqual(message); var $chat_content = chatboxview.$el.find('.chat-content');
expect(msg_obj.get('fullname')).toEqual(sender_jid); var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
expect(msg_obj.get('sender')).toEqual('them'); expect(msg_txt).toEqual(message);
expect(msg_obj.get('delayed')).toEqual(false); var sender_txt = $chat_content.find('span.chat-msg-them').text();
// Now check that the message appears inside the chatbox in the DOM expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy();
var $chat_content = chatboxview.$el.find('.chat-content');
var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
expect(msg_txt).toEqual(message);
var sender_txt = $chat_content.find('span.chat-msg-them').text();
expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy();
});
})); }));
}); });
...@@ -675,7 +668,7 @@ ...@@ -675,7 +668,7 @@
})); }));
}); });
it("will cause the chat area to be scrolled down only if it was at the bottom already", mock.initConverse(function (_converse) { it("will cause the chat area to be scrolled down only if it was at the bottom already", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
...@@ -684,27 +677,34 @@ ...@@ -684,27 +677,34 @@
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, sender_jid); test_utils.openChatBoxFor(_converse, sender_jid);
var chatboxview = _converse.chatboxviews.get(sender_jid); var chatboxview = _converse.chatboxviews.get(sender_jid);
spyOn(chatboxview, 'scrollDown').andCallThrough(); spyOn(chatboxview, 'scrollDown').and.callThrough();
runs(function () { var $chat_content = chatboxview.$el.find('.chat-content');
/* Create enough messages so that there's a /* Create enough messages so that there's a
* scrollbar. * scrollbar.
*/ */
for (var i=0; i<20; i++) { for (var i=0; i<20; i++) {
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
from: sender_jid, from: sender_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
type: 'chat', type: 'chat',
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('body').t('Message: '+i).up() }).c('body').t('Message: '+i).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
} }
});
waits(500); // Give enough time for `markScrolled` to have been called test_utils.waitUntil(function () {
runs(function () { return chatboxview.$content.scrollTop();
}, 300)
.then(function () {
return test_utils.waitUntil(function () {
return !chatboxview.model.get('auto_scrolled');
}, 300)
}).then(function () {
chatboxview.$content.scrollTop(0); chatboxview.$content.scrollTop(0);
}); return test_utils.waitUntil(function () {
waits(250); return chatboxview.model.get('scrolled');
runs(function () { }, 900)
}).then(function () {
_converse.chatboxes.onMessage($msg({ _converse.chatboxes.onMessage($msg({
from: sender_jid, from: sender_jid,
to: _converse.connection.jid, to: _converse.connection.jid,
...@@ -712,35 +712,40 @@ ...@@ -712,35 +712,40 @@
id: (new Date()).getTime() id: (new Date()).getTime()
}).c('body').t(message).up() }).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
});
waits(150);
runs(function () {
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
var $chat_content = chatboxview.$el.find('.chat-content'); var $chat_content = chatboxview.$el.find('.chat-content');
var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text(); var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
expect(chatboxview.model.get('scrolled')).toBeTruthy(); return test_utils.waitUntil(function () {
return chatboxview.$('.new-msgs-indicator').is(':visible');
}, 300)
}).then(function () {
expect(chatboxview.model.get('scrolled')).toBe(true);
expect(chatboxview.$content.scrollTop()).toBe(0); expect(chatboxview.$content.scrollTop()).toBe(0);
expect(chatboxview.$('.new-msgs-indicator').is(':visible')).toBeTruthy(); expect(chatboxview.$('.new-msgs-indicator').is(':visible')).toBeTruthy();
// Scroll down again // Scroll down again
chatboxview.$content.scrollTop(chatboxview.$content[0].scrollHeight); chatboxview.$content.scrollTop(chatboxview.$content[0].scrollHeight);
}); return test_utils.waitUntil(function () {
waits(250); return !chatboxview.$('.new-msgs-indicator').is(':visible');
runs(function () { }, 300)
expect(chatboxview.$('.new-msgs-indicator').is(':visible')).toBeFalsy(); }).then(done);
});
})); }));
it("is ignored if it's intended for a different resource and filter_by_resource is set to true", mock.initConverse(function (_converse) { it("is ignored if it's intended for a different resource and filter_by_resource is set to true",
mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
// Send a message from a different resource test_utils.waitUntil(function () {
var message, sender_jid, msg; return _converse.rosterview.$el.find('dt').length;
spyOn(_converse, 'log'); }, 300)
spyOn(_converse.chatboxes, 'getChatBox').andCallThrough(); .then(function () {
runs(function () { // Send a message from a different resource
var message, sender_jid, msg;
spyOn(_converse, 'log');
spyOn(_converse.chatboxes, 'getChatBox').and.callThrough();
_converse.filter_by_resource = true; _converse.filter_by_resource = true;
sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
msg = $msg({ msg = $msg({
...@@ -751,16 +756,12 @@ ...@@ -751,16 +756,12 @@
}).c('body').t("This message will not be shown").up() }).c('body').t("This message will not be shown").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
});
waits(50);
runs(function () {
expect(_converse.log).toHaveBeenCalledWith( expect(_converse.log).toHaveBeenCalledWith(
"onMessage: Ignoring incoming message intended for a different resource: dummy@localhost/some-other-resource", "info"); "onMessage: Ignoring incoming message intended for a different resource: dummy@localhost/some-other-resource", "info");
expect(_converse.chatboxes.getChatBox).not.toHaveBeenCalled(); expect(_converse.chatboxes.getChatBox).not.toHaveBeenCalled();
_converse.filter_by_resource = false; _converse.filter_by_resource = false;
});
waits(50);
runs(function () {
message = "This message sent to a different resource will be shown"; message = "This message sent to a different resource will be shown";
msg = $msg({ msg = $msg({
from: sender_jid, from: sender_jid,
...@@ -770,14 +771,13 @@ ...@@ -770,14 +771,13 @@
}).c('body').t(message).up() }).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
});
waits(50);
runs(function () {
expect(_converse.chatboxes.getChatBox).toHaveBeenCalled(); expect(_converse.chatboxes.getChatBox).toHaveBeenCalled();
var chatboxview = _converse.chatboxviews.get(sender_jid); var chatboxview = _converse.chatboxviews.get(sender_jid);
var $chat_content = chatboxview.$el.find('.chat-content:last'); var $chat_content = chatboxview.$el.find('.chat-content:last');
var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text(); var msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
done();
}); });
})); }));
}); });
...@@ -944,14 +944,19 @@ ...@@ -944,14 +944,19 @@
expect(chatbox).not.toBeDefined(); expect(chatbox).not.toBeDefined();
})); }));
it("received for a minimized chat box will increment a counter on its header", mock.initConverse(function (_converse) { it("received for a minimized chat box will increment a counter on its header",
mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
var contact_name = mock.cur_names[0]; test_utils.waitUntil(function () {
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; return _converse.rosterview.$el.find('dt').length;
runs(function () { }, 300)
spyOn(_converse, 'emit').andCallThrough(); .then(function () {
var contact_name = mock.cur_names[0];
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
spyOn(_converse, 'emit').and.callThrough();
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var chatview = _converse.chatboxviews.get(contact_jid); var chatview = _converse.chatboxviews.get(contact_jid);
expect(chatview.$el.is(':visible')).toBeTruthy(); expect(chatview.$el.is(':visible')).toBeTruthy();
...@@ -992,87 +997,94 @@ ...@@ -992,87 +997,94 @@
expect($count.html()).toBe('2'); expect($count.html()).toBe('2');
trimmedview.$el.find('.restore-chat').click(); trimmedview.$el.find('.restore-chat').click();
expect(trimmed_chatboxes.keys().length).toBe(0); expect(trimmed_chatboxes.keys().length).toBe(0);
done();
}); });
})); }));
it("will indicate when it has a time difference of more than a day between it and its predecessor", mock.initConverse(function (_converse) { it("will indicate when it has a time difference of more than a day between it and its predecessor",
mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 300)
.then(function () {
spyOn(_converse, 'emit');
var contact_name = mock.cur_names[1];
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid);
test_utils.clearChatBoxMessages(_converse, contact_jid);
var one_day_ago = moment();
one_day_ago.subtract('days', 1);
var message = 'This is a day old message';
var chatbox = _converse.chatboxes.get(contact_jid);
var chatboxview = _converse.chatboxviews.get(contact_jid);
var $chat_content = chatboxview.$el.find('.chat-content');
var msg_obj;
var msg_txt;
var sender_txt;
spyOn(_converse, 'emit'); var msg = $msg({
var contact_name = mock.cur_names[1]; from: contact_jid,
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost'; to: _converse.connection.jid,
test_utils.openChatBoxFor(_converse, contact_jid); type: 'chat',
test_utils.clearChatBoxMessages(_converse, contact_jid); id: one_day_ago.unix()
var one_day_ago = moment(); }).c('body').t(message).up()
one_day_ago.subtract('days', 1); .c('delay', { xmlns:'urn:xmpp:delay', from: 'localhost', stamp: one_day_ago.format() })
var message = 'This is a day old message'; .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
var chatbox = _converse.chatboxes.get(contact_jid); _converse.chatboxes.onMessage(msg);
var chatboxview = _converse.chatboxviews.get(contact_jid); expect(_converse.emit).toHaveBeenCalledWith('message', msg);
var $chat_content = chatboxview.$el.find('.chat-content'); expect(chatbox.messages.length).toEqual(1);
var msg_obj; msg_obj = chatbox.messages.models[0];
var msg_txt; expect(msg_obj.get('message')).toEqual(message);
var sender_txt; expect(msg_obj.get('fullname')).toEqual(contact_name);
expect(msg_obj.get('sender')).toEqual('them');
var msg = $msg({ expect(msg_obj.get('delayed')).toEqual(true);
from: contact_jid, msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text();
to: _converse.connection.jid, expect(msg_txt).toEqual(message);
type: 'chat', sender_txt = $chat_content.find('span.chat-msg-them').text();
id: one_day_ago.unix() expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy();
}).c('body').t(message).up()
.c('delay', { xmlns:'urn:xmpp:delay', from: 'localhost', stamp: one_day_ago.format() }) var $time = $chat_content.find('time');
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); expect($time.length).toEqual(1);
_converse.chatboxes.onMessage(msg); expect($time.attr('class')).toEqual('chat-info chat-date');
expect(_converse.emit).toHaveBeenCalledWith('message', msg); expect($time.data('isodate')).toEqual(moment(one_day_ago.startOf('day')).format());
expect(chatbox.messages.length).toEqual(1); expect($time.text()).toEqual(moment(one_day_ago.startOf('day')).format("dddd MMM Do YYYY"));
msg_obj = chatbox.messages.models[0];
expect(msg_obj.get('message')).toEqual(message); message = 'This is a current message';
expect(msg_obj.get('fullname')).toEqual(contact_name); msg = $msg({
expect(msg_obj.get('sender')).toEqual('them'); from: contact_jid,
expect(msg_obj.get('delayed')).toEqual(true); to: _converse.connection.jid,
msg_txt = $chat_content.find('.chat-message').find('.chat-msg-content').text(); type: 'chat',
expect(msg_txt).toEqual(message); id: new Date().getTime()
sender_txt = $chat_content.find('span.chat-msg-them').text(); }).c('body').t(message).up()
expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy(); .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.chatboxes.onMessage(msg);
var $time = $chat_content.find('time'); expect(_converse.emit).toHaveBeenCalledWith('message', msg);
expect($time.length).toEqual(1); // Check that there is a <time> element, with the required
expect($time.attr('class')).toEqual('chat-info chat-date'); // props.
expect($time.data('isodate')).toEqual(moment(one_day_ago.startOf('day')).format()); $time = $chat_content.find('time');
expect($time.text()).toEqual(moment(one_day_ago.startOf('day')).format("dddd MMM Do YYYY")); expect($time.length).toEqual(2); // There are now two time elements
$time = $chat_content.find('time:last'); // We check the last one
message = 'This is a current message'; var message_date = new Date();
msg = $msg({ expect($time.attr('class')).toEqual('chat-info chat-date');
from: contact_jid, expect($time.data('isodate')).toEqual(moment(message_date).startOf('day').format());
to: _converse.connection.jid, expect($time.text()).toEqual(moment(message_date).startOf('day').format("dddd MMM Do YYYY"));
type: 'chat',
id: new Date().getTime() // Normal checks for the 2nd message
}).c('body').t(message).up() expect(chatbox.messages.length).toEqual(2);
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); msg_obj = chatbox.messages.models[1];
_converse.chatboxes.onMessage(msg); expect(msg_obj.get('message')).toEqual(message);
expect(_converse.emit).toHaveBeenCalledWith('message', msg); expect(msg_obj.get('fullname')).toEqual(contact_name);
// Check that there is a <time> element, with the required expect(msg_obj.get('sender')).toEqual('them');
// props. expect(msg_obj.get('delayed')).toEqual(false);
$time = $chat_content.find('time'); msg_txt = $chat_content.find('.chat-message').last().find('.chat-msg-content').text();
expect($time.length).toEqual(2); // There are now two time elements expect(msg_txt).toEqual(message);
$time = $chat_content.find('time:last'); // We check the last one sender_txt = $chat_content.find('span.chat-msg-them').last().text();
var message_date = new Date(); expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy();
expect($time.attr('class')).toEqual('chat-info chat-date'); done();
expect($time.data('isodate')).toEqual(moment(message_date).startOf('day').format()); });
expect($time.text()).toEqual(moment(message_date).startOf('day').format("dddd MMM Do YYYY"));
// Normal checks for the 2nd message
expect(chatbox.messages.length).toEqual(2);
msg_obj = chatbox.messages.models[1];
expect(msg_obj.get('message')).toEqual(message);
expect(msg_obj.get('fullname')).toEqual(contact_name);
expect(msg_obj.get('sender')).toEqual('them');
expect(msg_obj.get('delayed')).toEqual(false);
msg_txt = $chat_content.find('.chat-message').last().find('.chat-msg-content').text();
expect(msg_txt).toEqual(message);
sender_txt = $chat_content.find('span.chat-msg-them').last().text();
expect(sender_txt.match(/^[0-9][0-9]:[0-9][0-9] /)).toBeTruthy();
})); }));
it("can be sent from a chatbox, and will appear inside it", mock.initConverse(function (_converse) { it("can be sent from a chatbox, and will appear inside it", mock.initConverse(function (_converse) {
...@@ -1086,11 +1098,11 @@ ...@@ -1086,11 +1098,11 @@
expect(_converse.emit).toHaveBeenCalledWith('chatBoxFocused', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxFocused', jasmine.any(Object));
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
var message = 'This message is sent from this chatbox'; var message = 'This message is sent from this chatbox';
spyOn(view, 'sendMessage').andCallThrough(); spyOn(view, 'sendMessage').and.callThrough();
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
expect(view.sendMessage).toHaveBeenCalled(); expect(view.sendMessage).toHaveBeenCalled();
expect(view.model.messages.length, 2); expect(view.model.messages.length, 2);
expect(_converse.emit.mostRecentCall.args, ['messageSend', message]); expect(_converse.emit.calls.mostRecent().args, ['messageSend', message]);
expect(view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content').text()).toEqual(message); expect(view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content').text()).toEqual(message);
})); }));
...@@ -1103,7 +1115,7 @@ ...@@ -1103,7 +1115,7 @@
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
var message = '<p>This message contains <em>some</em> <b>markup</b></p>'; var message = '<p>This message contains <em>some</em> <b>markup</b></p>';
spyOn(view, 'sendMessage').andCallThrough(); spyOn(view, 'sendMessage').and.callThrough();
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
expect(view.sendMessage).toHaveBeenCalled(); expect(view.sendMessage).toHaveBeenCalled();
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content'); var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
...@@ -1129,7 +1141,7 @@ ...@@ -1129,7 +1141,7 @@
'<span class="emoticon icon-shocked"></span>', '<span class="emoticon icon-thumbs-up"></span>', '<span class="emoticon icon-shocked"></span>', '<span class="emoticon icon-thumbs-up"></span>',
'<span class="emoticon icon-heart"></span>' '<span class="emoticon icon-heart"></span>'
]; ];
spyOn(view, 'sendMessage').andCallThrough(); spyOn(view, 'sendMessage').and.callThrough();
for (var i = 0; i < messages.length; i++) { for (var i = 0; i < messages.length; i++) {
var message = messages[i]; var message = messages[i];
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
...@@ -1148,17 +1160,12 @@ ...@@ -1148,17 +1160,12 @@
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
var message = 'This message contains a hyperlink: www.opkode.com'; var message = 'This message contains a hyperlink: www.opkode.com';
spyOn(view, 'sendMessage').andCallThrough(); spyOn(view, 'sendMessage').and.callThrough();
runs(function () { test_utils.sendMessage(view, message);
test_utils.sendMessage(view, message); expect(view.sendMessage).toHaveBeenCalled();
}); var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
waits(500); expect(msg.text()).toEqual(message);
runs(function () { expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
expect(view.sendMessage).toHaveBeenCalled();
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
});
})); }));
it("will have properly escaped URLs", mock.initConverse(function (_converse) { it("will have properly escaped URLs", mock.initConverse(function (_converse) {
...@@ -1170,54 +1177,44 @@ ...@@ -1170,54 +1177,44 @@
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
spyOn(view, 'sendMessage').andCallThrough(); spyOn(view, 'sendMessage').and.callThrough();
runs(function () { message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
message = "http://www.opkode.com/'onmouseover='alert(1)'whatever"; test_utils.sendMessage(view, message);
test_utils.sendMessage(view, message); expect(view.sendMessage).toHaveBeenCalled();
}); msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
waits(50); expect(msg.text()).toEqual(message);
runs(function () { expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
expect(view.sendMessage).toHaveBeenCalled();
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
message = 'http://www.opkode.com/"onmouseover="alert(1)"whatever'; message = 'http://www.opkode.com/"onmouseover="alert(1)"whatever';
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
});
waits(50);
runs(function () {
expect(view.sendMessage).toHaveBeenCalled();
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
message = "https://en.wikipedia.org/wiki/Ender's_Game"; expect(view.sendMessage).toHaveBeenCalled();
test_utils.sendMessage(view, message); msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
}); expect(msg.text()).toEqual(message);
waits(50); expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
runs(function () {
expect(view.sendMessage).toHaveBeenCalled();
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender\'s_Game</a>');
message = "https://en.wikipedia.org/wiki/Ender%27s_Game"; message = "https://en.wikipedia.org/wiki/Ender's_Game";
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
});
waits(50); expect(view.sendMessage).toHaveBeenCalled();
runs(function () { msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(view.sendMessage).toHaveBeenCalled(); expect(msg.text()).toEqual(message);
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content'); expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender\'s_Game</a>');
expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender%27s_Game</a>'); message = "https://en.wikipedia.org/wiki/Ender%27s_Game";
}); test_utils.sendMessage(view, message);
expect(view.sendMessage).toHaveBeenCalled();
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(msg.text()).toEqual(message);
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender%27s_Game</a>');
})); }));
it("will render images from their URLs", mock.initConverse(function (_converse) { it("will render images from their URLs", mock.initConverseWithAsync(function (done, _converse) {
if (/PhantomJS/.test(window.navigator.userAgent)) { if (/PhantomJS/.test(window.navigator.userAgent)) {
// Doesn't work when running tests in PhantomJS, since // Doesn't work when running tests in PhantomJS, since
// the page is loaded via file:/// // the page is loaded via file:///
done();
return; return;
} }
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
...@@ -1226,24 +1223,25 @@ ...@@ -1226,24 +1223,25 @@
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
spyOn(view, 'sendMessage').andCallThrough(); spyOn(view, 'sendMessage').and.callThrough();
runs(function () { test_utils.sendMessage(view, message);
test_utils.sendMessage(view, message);
}); test_utils.waitUntil(function () {
waits(500); return view.$el.find('.chat-content').find('.chat-message img').length;
runs(function () { }, 300).then(function () {
expect(view.sendMessage).toHaveBeenCalled(); expect(view.sendMessage).toHaveBeenCalled();
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content'); var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(msg.html()).toEqual('<img src="'+message+'" class="chat-image">'); expect(msg.html()).toEqual('<img src="'+message+'" class="chat-image">');
message += "?param1=val1&param2=val2"; message += "?param1=val1&param2=val2";
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
}); return test_utils.waitUntil(function () {
waits(500); return view.$el.find('.chat-content').find('.chat-message img').length === 2;
runs(function () { }, 300)
}).then(function () {
expect(view.sendMessage).toHaveBeenCalled(); expect(view.sendMessage).toHaveBeenCalled();
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content'); var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
expect(msg.html()).toEqual('<img src="'+message.replace(/&/g, '&amp;')+'" class="chat-image">'); expect(msg.html()).toEqual('<img src="'+message.replace(/&/g, '&amp;')+'" class="chat-image">');
done();
}); });
})); }));
...@@ -1290,77 +1288,83 @@ ...@@ -1290,77 +1288,83 @@
describe("An active notification", function () { describe("An active notification", function () {
it("is sent when the user opens a chat box", mock.initConverse(function (_converse) { it("is sent when the user opens a chat box", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
waits(300); // ChatBox.show() is debounced for 250ms return _converse.rosterview.$el.find('dt').length;
runs(function () { }, 300).then(function () {
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
expect(view.model.get('chat_state')).toBe('active'); expect(view.model.get('chat_state')).toBe('active');
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.attr('to')).toBe(contact_jid); expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().length).toBe(3); expect($stanza.children().length).toBe(3);
expect($stanza.children().get(0).tagName).toBe('active'); expect($stanza.children().get(0).tagName).toBe('active');
expect($stanza.children().get(1).tagName).toBe('no-store'); expect($stanza.children().get(1).tagName).toBe('no-store');
expect($stanza.children().get(2).tagName).toBe('no-permanent-store'); expect($stanza.children().get(2).tagName).toBe('no-permanent-store');
done();
}); });
})); }));
it("is sent when the user maximizes a minimized a chat box", mock.initConverse(function (_converse) { it("is sent when the user maximizes a minimized a chat box", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
runs(function () { test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 300).then(function () {
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
});
waits(300); // ChatBox.show() is debounced for 250ms
runs(function () {
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
view.model.minimize(); view.model.minimize();
expect(view.model.get('chat_state')).toBe('inactive'); expect(view.model.get('chat_state')).toBe('inactive');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
view.model.maximize(); view.model.maximize();
expect(view.model.get('chat_state')).toBe('active'); return test_utils.waitUntil(function () {
return view.model.get('chat_state') === 'active';
}, 300)
}).then(function () {
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.attr('to')).toBe(contact_jid); expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().length).toBe(3); expect($stanza.children().length).toBe(3);
expect($stanza.children().get(0).tagName).toBe('active'); expect($stanza.children().get(0).tagName).toBe('active');
expect($stanza.children().get(1).tagName).toBe('no-store'); expect($stanza.children().get(1).tagName).toBe('no-store');
expect($stanza.children().get(2).tagName).toBe('no-permanent-store'); expect($stanza.children().get(2).tagName).toBe('no-permanent-store');
done();
}); });
})); }));
}); });
describe("A composing notification", function () { describe("A composing notification", function () {
it("is sent as soon as the user starts typing a message which is not a command", mock.initConverse(function (_converse) { it("is sent as soon as the user starts typing a message which is not a command", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
waits(300); // ChatBox.show() is debounced for 250ms return _converse.rosterview.$el.find('dt').length;
runs(function () { }, 300)
.then(function () {
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
expect(view.model.get('chat_state')).toBe('active'); expect(view.model.get('chat_state')).toBe('active');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
spyOn(_converse, 'emit');
view.keyPressed({ view.keyPressed({
target: view.$el.find('textarea.chat-textarea'), target: view.$el.find('textarea.chat-textarea'),
keyCode: 1 keyCode: 1
}); });
expect(view.model.get('chat_state')).toBe('composing'); expect(view.model.get('chat_state')).toBe('composing');
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.attr('to')).toBe(contact_jid); expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().get(0).tagName).toBe('composing'); expect($stanza.children().get(0).tagName).toBe('composing');
expect($stanza.children().get(1).tagName).toBe('no-store'); expect($stanza.children().get(1).tagName).toBe('no-store');
...@@ -1372,7 +1376,8 @@ ...@@ -1372,7 +1376,8 @@
keyCode: 1 keyCode: 1
}); });
expect(view.model.get('chat_state')).toBe('composing'); expect(view.model.get('chat_state')).toBe('composing');
expect(_converse.emit.callCount, 1); expect(_converse.emit.calls.count(), 1);
done();
}); });
})); }));
...@@ -1441,20 +1446,22 @@ ...@@ -1441,20 +1446,22 @@
describe("A paused notification", function () { describe("A paused notification", function () {
it("is sent if the user has stopped typing since 30 seconds", mock.initConverse(function (_converse) { it("is sent if the user has stopped typing since 30 seconds", mock.initConverseWithAsync(function (done, _converse) {
var view, contact_jid;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 300)
.then(function () {
_converse.TIMEOUTS.PAUSED = 200; // Make the timeout shorter so that we can test
var view, contact_jid;
_converse.TIMEOUTS.PAUSED = 200; // Make the timeout shorter so that we can test
waits(300); // ChatBox.show() is debounced for 250ms
runs(function () {
contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
spyOn(view, 'setChatState').andCallThrough(); spyOn(view, 'setChatState').and.callThrough();
expect(view.model.get('chat_state')).toBe('active'); expect(view.model.get('chat_state')).toBe('active');
view.keyPressed({ view.keyPressed({
target: view.$el.find('textarea.chat-textarea'), target: view.$el.find('textarea.chat-textarea'),
...@@ -1462,14 +1469,14 @@ ...@@ -1462,14 +1469,14 @@
}); });
expect(view.model.get('chat_state')).toBe('composing'); expect(view.model.get('chat_state')).toBe('composing');
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.children().get(0).tagName).toBe('composing'); expect($stanza.children().get(0).tagName).toBe('composing');
}); return test_utils.waitUntil(function () {
waits(250); return view.model.get('chat_state') === 'paused';
runs(function () { }, 500)
expect(view.model.get('chat_state')).toBe('paused'); }).then(function () {
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[1][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(1)[0].tree());
expect($stanza.attr('to')).toBe(contact_jid); expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().length).toBe(3); expect($stanza.children().length).toBe(3);
expect($stanza.children().get(0).tagName).toBe('paused'); expect($stanza.children().get(0).tagName).toBe('paused');
...@@ -1484,42 +1491,42 @@ ...@@ -1484,42 +1491,42 @@
}); });
expect(view.setChatState).toHaveBeenCalled(); expect(view.setChatState).toHaveBeenCalled();
expect(view.model.get('chat_state')).toBe('composing'); expect(view.model.get('chat_state')).toBe('composing');
});
waits(100);
runs(function () {
view.keyPressed({ view.keyPressed({
target: view.$el.find('textarea.chat-textarea'), target: view.$el.find('textarea.chat-textarea'),
keyCode: 1 keyCode: 1
}); });
expect(view.model.get('chat_state')).toBe('composing'); expect(view.model.get('chat_state')).toBe('composing');
}); done();
waits(150);
runs(function () {
expect(view.model.get('chat_state')).toBe('composing');
}); });
})); }));
it("will be shown if received", mock.initConverse(function (_converse) { it("will be shown if received", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
// TODO: only show paused state if the previous state was composing return _converse.rosterview.$el.find('dt').length;
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions }, 300)
spyOn(_converse, 'emit'); .then(function () {
var sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; // TODO: only show paused state if the previous state was composing
// <paused> state // See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
var msg = $msg({ spyOn(_converse, 'emit');
from: sender_jid, var sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
to: _converse.connection.jid, // <paused> state
type: 'chat', var msg = $msg({
id: (new Date()).getTime() from: sender_jid,
}).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree(); to: _converse.connection.jid,
_converse.chatboxes.onMessage(msg); type: 'chat',
expect(_converse.emit).toHaveBeenCalledWith('message', msg); id: (new Date()).getTime()
var chatboxview = _converse.chatboxviews.get(sender_jid); }).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
var $events = chatboxview.$el.find('.chat-event'); _converse.chatboxes.onMessage(msg);
expect($events.text()).toEqual(mock.cur_names[1] + ' has stopped typing'); expect(_converse.emit).toHaveBeenCalledWith('message', msg);
var chatboxview = _converse.chatboxviews.get(sender_jid);
var $events = chatboxview.$el.find('.chat-event');
expect($events.text()).toEqual(mock.cur_names[1] + ' has stopped typing');
done();
});
})); }));
it("can be a paused carbon message that this user sent from a different client", mock.initConverse(function (_converse) { it("can be a paused carbon message that this user sent from a different client", mock.initConverse(function (_converse) {
...@@ -1562,41 +1569,53 @@ ...@@ -1562,41 +1569,53 @@
describe("An inactive notifciation", function () { describe("An inactive notifciation", function () {
it("is sent if the user has stopped typing since 2 minutes", mock.initConverse(function (_converse) { it("is sent if the user has stopped typing since 2 minutes", mock.initConverseWithAsync(function (done, _converse) {
var view, contact_jid;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
// Make the timeouts shorter so that we can test return _converse.rosterview.$el.find('dt').length;
_converse.TIMEOUTS.PAUSED = 200; }, 300).then(function () {
_converse.TIMEOUTS.INACTIVE = 200; // Make the timeouts shorter so that we can test
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; _converse.TIMEOUTS.PAUSED = 200;
test_utils.openChatBoxFor(_converse, contact_jid); _converse.TIMEOUTS.INACTIVE = 200;
var view = _converse.chatboxviews.get(contact_jid); contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
runs(function () { test_utils.openChatBoxFor(_converse, contact_jid);
view = _converse.chatboxviews.get(contact_jid);
expect(view.model.get('chat_state')).toBe('active'); expect(view.model.get('chat_state')).toBe('active');
view.keyPressed({ view.keyPressed({
target: view.$el.find('textarea.chat-textarea'), target: view.$el.find('textarea.chat-textarea'),
keyCode: 1 keyCode: 1
}); });
expect(view.model.get('chat_state')).toBe('composing'); expect(view.model.get('chat_state')).toBe('composing');
});
waits(250);
runs(function () {
expect(view.model.get('chat_state')).toBe('paused');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
}); return test_utils.waitUntil(function () {
waits(250); if (view.model.get('chat_state') === 'paused') {
runs(function () { return true;
expect(view.model.get('chat_state')).toBe('inactive'); }
return false;
}, 250)
}).then(function () {
return test_utils.waitUntil(function () {
return view.model.get('chat_state') === 'inactive';
}, 250)
}).then(function () {
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.first().args[0].tree());
expect($stanza.attr('to')).toBe(contact_jid); expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().length).toBe(3); expect($stanza.children().length).toBe(3);
expect($stanza.children().get(0).tagName).toBe('inactive'); expect($stanza.children().get(0).tagName).toBe('paused');
expect($stanza.children().get(1).tagName).toBe('no-store'); expect($stanza.children().get(1).tagName).toBe('no-store');
expect($stanza.children().get(2).tagName).toBe('no-permanent-store'); expect($stanza.children().get(2).tagName).toBe('no-permanent-store');
$stanza = $(_converse.connection.send.calls.mostRecent().args[0].tree());
expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().length).toBe(3);
expect($stanza.children().get(0).tagName).toBe('inactive');
expect($stanza.children().get(1).tagName).toBe('no-store');
expect($stanza.children().get(2).tagName).toBe('no-permanent-store');
done();
}); });
})); }));
...@@ -1612,18 +1631,18 @@ ...@@ -1612,18 +1631,18 @@
view.minimize(); view.minimize();
expect(view.model.get('chat_state')).toBe('inactive'); expect(view.model.get('chat_state')).toBe('inactive');
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.attr('to')).toBe(contact_jid); expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().get(0).tagName).toBe('inactive'); expect($stanza.children().get(0).tagName).toBe('inactive');
})); }));
it("is sent if the user closes a chat box", mock.initConverse(function (_converse) { it("is sent if the user closes a chat box", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
waits(300); // ChatBox.show() is debounced for 250ms return _converse.rosterview.$el.find('dt').length;
runs(function () { }, 300).then(function () {
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid); test_utils.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); var view = _converse.chatboxviews.get(contact_jid);
...@@ -1632,12 +1651,13 @@ ...@@ -1632,12 +1651,13 @@
view.close(); view.close();
expect(view.model.get('chat_state')).toBe('inactive'); expect(view.model.get('chat_state')).toBe('inactive');
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.attr('to')).toBe(contact_jid); expect($stanza.attr('to')).toBe(contact_jid);
expect($stanza.children().length).toBe(3); expect($stanza.children().length).toBe(3);
expect($stanza.children().get(0).tagName).toBe('inactive'); expect($stanza.children().get(0).tagName).toBe('inactive');
expect($stanza.children().get(1).tagName).toBe('no-store'); expect($stanza.children().get(1).tagName).toBe('no-store');
expect($stanza.children().get(2).tagName).toBe('no-permanent-store'); expect($stanza.children().get(2).tagName).toBe('no-permanent-store');
done();
}); });
})); }));
...@@ -1713,9 +1733,9 @@ ...@@ -1713,9 +1733,9 @@
expect(_converse.emit).toHaveBeenCalledWith('messageSend', message); expect(_converse.emit).toHaveBeenCalledWith('messageSend', message);
message = '/clear'; message = '/clear';
spyOn(view, 'onMessageSubmitted').andCallThrough(); spyOn(view, 'onMessageSubmitted').and.callThrough();
spyOn(view, 'clearMessages').andCallThrough(); spyOn(view, 'clearMessages').and.callThrough();
spyOn(window, 'confirm').andCallFake(function () { spyOn(window, 'confirm').and.callFake(function () {
return true; return true;
}); });
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
...@@ -1724,8 +1744,8 @@ ...@@ -1724,8 +1744,8 @@
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(view.model.messages.length, 0); // The messages must be removed from the chatbox expect(view.model.messages.length, 0); // The messages must be removed from the chatbox
expect(view.model.messages.browserStorage.records.length, 0); // And also from browserStorage expect(view.model.messages.browserStorage.records.length, 0); // And also from browserStorage
expect(_converse.emit.callCount, 1); expect(_converse.emit.calls.count(), 1);
expect(_converse.emit.mostRecentCall.args, ['messageSend', message]); expect(_converse.emit.calls.mostRecent().args, ['messageSend', message]);
})); }));
}); });
...@@ -1738,7 +1758,7 @@ ...@@ -1738,7 +1758,7 @@
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
expect(_converse.msg_counter).toBe(0); expect(_converse.msg_counter).toBe(0);
spyOn(_converse, 'incrementMsgCounter').andCallThrough(); spyOn(_converse, 'incrementMsgCounter').and.callThrough();
var previous_state = _converse.windowState; var previous_state = _converse.windowState;
var message = 'This message will increment the message counter'; var message = 'This message will increment the message counter';
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
...@@ -1761,17 +1781,11 @@ ...@@ -1761,17 +1781,11 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
_converse.windowState = 'hidden'; _converse.windowState = 'hidden';
spyOn(_converse, 'clearMsgCounter').andCallThrough(); spyOn(_converse, 'clearMsgCounter').and.callThrough();
runs(function () { _converse.saveWindowState(null, 'focus');
_converse.saveWindowState(null, 'focus'); _converse.saveWindowState(null, 'blur');
_converse.saveWindowState(null, 'blur'); expect(_converse.clearMsgCounter).toHaveBeenCalled();
});
waits(50);
runs(function () {
expect(_converse.clearMsgCounter).toHaveBeenCalled();
});
})); }));
it("is not incremented when the message is received and the window is focused", mock.initConverse(function (_converse) { it("is not incremented when the message is received and the window is focused", mock.initConverse(function (_converse) {
...@@ -1780,7 +1794,7 @@ ...@@ -1780,7 +1794,7 @@
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
expect(_converse.msg_counter).toBe(0); expect(_converse.msg_counter).toBe(0);
spyOn(_converse, 'incrementMsgCounter').andCallThrough(); spyOn(_converse, 'incrementMsgCounter').and.callThrough();
_converse.saveWindowState(null, 'focus'); _converse.saveWindowState(null, 'focus');
var message = 'This message will not increment the message counter'; var message = 'This message will not increment the message counter';
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils", "utils" ], factory); define(["mock", "converse-core", "test-utils", "utils" ], factory);
} (this, function (mock, converse, test_utils, utils) { } (this, function (mock, converse, test_utils, utils) {
var _ = converse.env._; var _ = converse.env._;
var $ = converse.env.jQuery; var $ = converse.env.jQuery;
...@@ -13,48 +13,44 @@ ...@@ -13,48 +13,44 @@
it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments", mock.initConverse(function (_converse) { it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments", mock.initConverse(function (_converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
runs(function () { test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'leisure', 'localhost', 'dummy');
test_utils.openAndEnterChatRoom(_converse, 'leisure', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'news', 'localhost', 'dummy');
test_utils.openAndEnterChatRoom(_converse, 'news', 'localhost', 'dummy'); expect(_converse.chatboxviews.get('lounge@localhost').$el.is(':visible')).toBeTruthy();
expect(_converse.chatboxviews.get('lounge@localhost').$el.is(':visible')).toBeTruthy(); expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy();
expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy(); expect(_converse.chatboxviews.get('news@localhost').$el.is(':visible')).toBeTruthy();
expect(_converse.chatboxviews.get('news@localhost').$el.is(':visible')).toBeTruthy();
}); // XXX: bit of a cheat here. We want `cleanup()` to be
waits('100'); // called on the room. Either it's this or faking
runs(function () { // `sendPresence`.
// XXX: bit of a cheat here. We want `cleanup()` to be _converse.connection.connected = false;
// called on the room. Either it's this or faking
// `sendPresence`. _converse.api.rooms.close('lounge@localhost');
_converse.connection.connected = false; expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy();
_converse.api.rooms.close('lounge@localhost'); expect(_converse.chatboxviews.get('news@localhost').$el.is(':visible')).toBeTruthy();
expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy(); _converse.api.rooms.close(['leisure@localhost', 'news@localhost']);
expect(_converse.chatboxviews.get('news@localhost').$el.is(':visible')).toBeTruthy(); expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
_converse.api.rooms.close(['leisure@localhost', 'news@localhost']); expect(_converse.chatboxviews.get('news@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('news@localhost')).toBeUndefined();
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
test_utils.openAndEnterChatRoom(_converse, 'leisure', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'leisure', 'localhost', 'dummy');
expect(_converse.chatboxviews.get('lounge@localhost').$el.is(':visible')).toBeTruthy(); expect(_converse.chatboxviews.get('lounge@localhost').$el.is(':visible')).toBeTruthy();
expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy(); expect(_converse.chatboxviews.get('leisure@localhost').$el.is(':visible')).toBeTruthy();
});
waits('100'); _converse.api.rooms.close();
runs(function () { expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
_converse.api.rooms.close(); expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('lounge@localhost')).toBeUndefined();
expect(_converse.chatboxviews.get('leisure@localhost')).toBeUndefined();
});
})); }));
it("has a method 'get' which returns a wrapped chat room (if it exists)", mock.initConverse(function (_converse) { it("has a method 'get' which returns a wrapped chat room (if it exists)", mock.initConverseWithAsync(function (done, _converse) {
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
waits('300'); // ChatBox.show() is debounced for 250ms test_utils.waitUntil(function () {
runs(function () { return _converse.rosterview.$el.find('dt').length;
}, 300)
.then(function () {
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var jid = 'lounge@localhost'; var jid = 'lounge@localhost';
var room = _converse.api.rooms.get(jid); var room = _converse.api.rooms.get(jid);
...@@ -63,23 +59,19 @@ ...@@ -63,23 +59,19 @@
var chatroomview = _converse.chatboxviews.get(jid); var chatroomview = _converse.chatboxviews.get(jid);
expect(chatroomview.$el.is(':visible')).toBeTruthy(); expect(chatroomview.$el.is(':visible')).toBeTruthy();
chatroomview.close(); chatroomview.close();
});
waits('300'); // ChatBox.show() is debounced for 250ms
runs(function () {
// Test with mixed case // Test with mixed case
test_utils.openAndEnterChatRoom(_converse, 'Leisure', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'Leisure', 'localhost', 'dummy');
var jid = 'Leisure@localhost'; jid = 'Leisure@localhost';
var room = _converse.api.rooms.get(jid); room = _converse.api.rooms.get(jid);
expect(room instanceof Object).toBeTruthy(); expect(room instanceof Object).toBeTruthy();
var chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
expect(chatroomview.$el.is(':visible')).toBeTruthy(); expect(chatroomview.$el.is(':visible')).toBeTruthy();
});
waits('300'); // ChatBox.show() is debounced for 250ms jid = 'leisure@localhost';
runs(function () { room = _converse.api.rooms.get(jid);
var jid = 'leisure@localhost';
var room = _converse.api.rooms.get(jid);
expect(room instanceof Object).toBeTruthy(); expect(room instanceof Object).toBeTruthy();
var chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
expect(chatroomview.$el.is(':visible')).toBeTruthy(); expect(chatroomview.$el.is(':visible')).toBeTruthy();
jid = 'leiSure@localhost'; jid = 'leiSure@localhost';
...@@ -93,41 +85,41 @@ ...@@ -93,41 +85,41 @@
jid = 'lounge2@localhost'; jid = 'lounge2@localhost';
room = _converse.api.rooms.get(jid); room = _converse.api.rooms.get(jid);
expect(typeof room === 'undefined').toBeTruthy(); expect(typeof room === 'undefined').toBeTruthy();
done();
}); });
})); }));
it("has a method 'open' which opens (optionally configures) and returns a wrapped chat box", mock.initConverse(function (_converse) { it("has a method 'open' which opens (optionally configures) and returns a wrapped chat box", mock.initConverseWithAsync(function (done, _converse) {
// Mock 'getRoomFeatures', otherwise the room won't be // Mock 'getRoomFeatures', otherwise the room won't be
// displayed as it waits first for the features to be returned // displayed as it waits first for the features to be returned
// (when it's a new room being created). // (when it's a new room being created).
spyOn(_converse.ChatRoomView.prototype, 'getRoomFeatures').andCallFake(function () { spyOn(_converse.ChatRoomView.prototype, 'getRoomFeatures').and.callFake(function () {
var deferred = new $.Deferred(); var deferred = new $.Deferred();
deferred.resolve(); deferred.resolve();
return deferred.promise(); return deferred.promise();
}); });
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
var chatroomview; test_utils.waitUntil(function () {
var jid = 'lounge@localhost'; return _converse.rosterview.$el.find('dt').length;
var room = _converse.api.rooms.open(jid); }, 300)
runs(function () { .then(function () {
var chatroomview;
var jid = 'lounge@localhost';
var room = _converse.api.rooms.open(jid);
// Test on chat room that doesn't exist. // Test on chat room that doesn't exist.
expect(room instanceof Object).toBeTruthy(); expect(room instanceof Object).toBeTruthy();
expect(room.is_chatroom).toBeTruthy(); expect(room.is_chatroom).toBeTruthy();
chatroomview = _converse.chatboxviews.get(jid); chatroomview = _converse.chatboxviews.get(jid);
expect(chatroomview.$el.is(':visible')).toBeTruthy(); expect(chatroomview.$el.is(':visible')).toBeTruthy();
});
waits('300'); // ChatBox.show() is debounced for 250ms
runs(function () {
// Test again, now that the room exists. // Test again, now that the room exists.
room = _converse.api.rooms.open(jid); room = _converse.api.rooms.open(jid);
expect(room instanceof Object).toBeTruthy(); expect(room instanceof Object).toBeTruthy();
expect(room.is_chatroom).toBeTruthy(); expect(room.is_chatroom).toBeTruthy();
chatroomview = _converse.chatboxviews.get(jid); chatroomview = _converse.chatboxviews.get(jid);
expect(chatroomview.$el.is(':visible')).toBeTruthy(); expect(chatroomview.$el.is(':visible')).toBeTruthy();
});
waits('300'); // ChatBox.show() is debounced for 250ms
runs(function () {
// Test with mixed case in JID // Test with mixed case in JID
jid = 'Leisure@localhost'; jid = 'Leisure@localhost';
room = _converse.api.rooms.open(jid); room = _converse.api.rooms.open(jid);
...@@ -147,13 +139,11 @@ ...@@ -147,13 +139,11 @@
chatroomview = _converse.chatboxviews.get(jid.toLowerCase()); chatroomview = _converse.chatboxviews.get(jid.toLowerCase());
expect(chatroomview.$el.is(':visible')).toBeTruthy(); expect(chatroomview.$el.is(':visible')).toBeTruthy();
chatroomview.close(); chatroomview.close();
});
waits('300'); // ChatBox.show() is debounced for 250ms
runs(function () {
_converse.muc_instant_rooms = false; _converse.muc_instant_rooms = false;
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -246,6 +236,7 @@ ...@@ -246,6 +236,7 @@
expect($sent_stanza.find('field[var="muc#roomconfig_whois"] value ').text()).toBe('anyone'); expect($sent_stanza.find('field[var="muc#roomconfig_whois"] value ').text()).toBe('anyone');
expect($sent_stanza.find('field[var="muc#roomconfig_membersonly"] value').text()).toBe('1'); expect($sent_stanza.find('field[var="muc#roomconfig_membersonly"] value').text()).toBe('1');
expect($sent_stanza.find('field[var="muc#roomconfig_historylength"] value').text()).toBe('20'); expect($sent_stanza.find('field[var="muc#roomconfig_historylength"] value').text()).toBe('20');
done();
}); });
})); }));
}); });
...@@ -254,7 +245,7 @@ ...@@ -254,7 +245,7 @@
it("will be created when muc_instant_rooms is set to true", mock.initConverse(function (_converse) { it("will be created when muc_instant_rooms is set to true", mock.initConverse(function (_converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -280,7 +271,7 @@ ...@@ -280,7 +271,7 @@
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'join').andCallThrough(); spyOn(view, 'join').and.callThrough();
/* <iq to="myroom@conference.chat.example.org" /* <iq to="myroom@conference.chat.example.org"
* from="jordie.langen@chat.example.org/converse.js-11659299" * from="jordie.langen@chat.example.org/converse.js-11659299"
...@@ -446,12 +437,12 @@ ...@@ -446,12 +437,12 @@
it("shows its description in the chat heading", mock.initConverse(function (_converse) { it("shows its description in the chat heading", mock.initConverse(function (_converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
var view = _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'}); var view = _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'});
spyOn(view, 'generateHeadingHTML').andCallThrough(); spyOn(view, 'generateHeadingHTML').and.callThrough();
var features_stanza = $iq({ var features_stanza = $iq({
from: 'coven@chat.shakespeare.lit', from: 'coven@chat.shakespeare.lit',
'id': IQ_id, 'id': IQ_id,
...@@ -541,221 +532,214 @@ ...@@ -541,221 +532,214 @@
var view; var view;
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
runs(function () {
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'});
view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
spyOn(view, 'saveAffiliationAndRole').andCallThrough();
// We pretend this is a new room, so no disco info is returned. _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'});
var features_stanza = $iq({ view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
from: 'coven@chat.shakespeare.lit', spyOn(view, 'saveAffiliationAndRole').and.callThrough();
'id': IQ_id,
'to': 'dummy@localhost/desktop',
'type': 'error'
}).c('error', {'type': 'cancel'})
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
_converse.connection._dataRecv(test_utils.createRequest(features_stanza));
/* <presence to="dummy@localhost/_converse.js-29092160" // We pretend this is a new room, so no disco info is returned.
* from="coven@chat.shakespeare.lit/some1"> var features_stanza = $iq({
* <x xmlns="http://jabber.org/protocol/muc#user"> from: 'coven@chat.shakespeare.lit',
* <item affiliation="owner" jid="dummy@localhost/_converse.js-29092160" role="moderator"/> 'id': IQ_id,
* <status code="110"/> 'to': 'dummy@localhost/desktop',
* </x> 'type': 'error'
* </presence></body> }).c('error', {'type': 'cancel'})
*/ .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
var presence = $pres({ _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
to: 'dummy@localhost/_converse.js-29092160',
from: 'coven@chat.shakespeare.lit/some1'
}).c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'owner',
'jid': 'dummy@localhost/_converse.js-29092160',
'role': 'moderator'
}).up()
.c('status', {code: '110'});
_converse.connection._dataRecv(test_utils.createRequest(presence));
expect(view.saveAffiliationAndRole).toHaveBeenCalled();
expect(view.$('.configure-chatroom-button').is(':visible')).toBeTruthy();
expect(view.$('.toggle-chatbox-button').is(':visible')).toBeTruthy();
expect(view.$('.toggle-bookmark').is(':visible')).toBeTruthy();
view.$('.configure-chatroom-button').click();
});
waits(50);
runs (function () {
/* Check that an IQ is sent out, asking for the
* configuration form.
* See: // http://xmpp.org/extensions/xep-0045.html#example-163
*
* <iq from='crone1@shakespeare.lit/desktop'
* id='config1'
* to='coven@chat.shakespeare.lit'
* type='get'>
* <query xmlns='http://jabber.org/protocol/muc#owner'/>
* </iq>
*/
expect(sent_IQ.toLocaleString()).toBe(
"<iq to='coven@chat.shakespeare.lit' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<query xmlns='http://jabber.org/protocol/muc#owner'/>"+
"</iq>");
/* Server responds with the configuration form. /* <presence to="dummy@localhost/_converse.js-29092160"
* See: // http://xmpp.org/extensions/xep-0045.html#example-165 * from="coven@chat.shakespeare.lit/some1">
*/ * <x xmlns="http://jabber.org/protocol/muc#user">
var config_stanza = $iq({from: 'coven@chat.shakespeare.lit', * <item affiliation="owner" jid="dummy@localhost/_converse.js-29092160" role="moderator"/>
'id': IQ_id, * <status code="110"/>
'to': 'dummy@localhost/desktop', * </x>
'type': 'result'}) * </presence></body>
.c('query', { 'xmlns': 'http://jabber.org/protocol/muc#owner'}) */
.c('x', { 'xmlns': 'jabber:x:data', 'type': 'form'}) var presence = $pres({
.c('title').t('Configuration for "coven" Room').up() to: 'dummy@localhost/_converse.js-29092160',
.c('instructions').t('Complete this form to modify the configuration of your room.').up() from: 'coven@chat.shakespeare.lit/some1'
.c('field', {'type': 'hidden', 'var': 'FORM_TYPE'}) }).c('x', {xmlns: Strophe.NS.MUC_USER})
.c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up() .c('item', {
.c('field', { 'affiliation': 'owner',
'label': 'Natural-Language Room Name', 'jid': 'dummy@localhost/_converse.js-29092160',
'type': 'text-single', 'role': 'moderator'
'var': 'muc#roomconfig_roomname'}) }).up()
.c('value').t('A Dark Cave').up().up() .c('status', {code: '110'});
.c('field', { _converse.connection._dataRecv(test_utils.createRequest(presence));
'label': 'Short Description of Room', expect(view.saveAffiliationAndRole).toHaveBeenCalled();
'type': 'text-single', expect(view.$('.configure-chatroom-button').is(':visible')).toBeTruthy();
'var': 'muc#roomconfig_roomdesc'}) expect(view.$('.toggle-chatbox-button').is(':visible')).toBeTruthy();
.c('value').t('The place for all good witches!').up().up() expect(view.$('.toggle-bookmark').is(':visible')).toBeTruthy();
.c('field', { view.$('.configure-chatroom-button').click();
'label': 'Enable Public Logging?',
'type': 'boolean', /* Check that an IQ is sent out, asking for the
'var': 'muc#roomconfig_enablelogging'}) * configuration form.
.c('value').t(0).up().up() * See: // http://xmpp.org/extensions/xep-0045.html#example-163
.c('field', { *
'label': 'Allow Occupants to Change Subject?', * <iq from='crone1@shakespeare.lit/desktop'
'type': 'boolean', * id='config1'
'var': 'muc#roomconfig_changesubject'}) * to='coven@chat.shakespeare.lit'
.c('value').t(0).up().up() * type='get'>
.c('field', { * <query xmlns='http://jabber.org/protocol/muc#owner'/>
'label': 'Allow Occupants to Invite Others?', * </iq>
'type': 'boolean', */
'var': 'muc#roomconfig_allowinvites'}) expect(sent_IQ.toLocaleString()).toBe(
.c('value').t(0).up().up() "<iq to='coven@chat.shakespeare.lit' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+
.c('field', { "<query xmlns='http://jabber.org/protocol/muc#owner'/>"+
'label': 'Who Can Send Private Messages?', "</iq>");
'type': 'list-single',
'var': 'muc#roomconfig_allowpm'}) /* Server responds with the configuration form.
.c('value').t('anyone').up() * See: // http://xmpp.org/extensions/xep-0045.html#example-165
.c('option', {'label': 'Anyone'}) */
.c('value').t('anyone').up().up() var config_stanza = $iq({from: 'coven@chat.shakespeare.lit',
.c('option', {'label': 'Anyone with Voice'}) 'id': IQ_id,
.c('value').t('participants').up().up() 'to': 'dummy@localhost/desktop',
.c('option', {'label': 'Moderators Only'}) 'type': 'result'})
.c('value').t('moderators').up().up() .c('query', { 'xmlns': 'http://jabber.org/protocol/muc#owner'})
.c('option', {'label': 'Nobody'}) .c('x', { 'xmlns': 'jabber:x:data', 'type': 'form'})
.c('value').t('none').up().up().up() .c('title').t('Configuration for "coven" Room').up()
.c('field', { .c('instructions').t('Complete this form to modify the configuration of your room.').up()
'label': 'Roles for which Presence is Broadcasted', .c('field', {'type': 'hidden', 'var': 'FORM_TYPE'})
'type': 'list-multi', .c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up()
'var': 'muc#roomconfig_presencebroadcast'}) .c('field', {
.c('value').t('moderator').up() 'label': 'Natural-Language Room Name',
.c('value').t('participant').up() 'type': 'text-single',
.c('value').t('visitor').up() 'var': 'muc#roomconfig_roomname'})
.c('option', {'label': 'Moderator'}) .c('value').t('A Dark Cave').up().up()
.c('value').t('moderator').up().up() .c('field', {
.c('option', {'label': 'Participant'}) 'label': 'Short Description of Room',
.c('value').t('participant').up().up() 'type': 'text-single',
.c('option', {'label': 'Visitor'}) 'var': 'muc#roomconfig_roomdesc'})
.c('value').t('visitor').up().up().up() .c('value').t('The place for all good witches!').up().up()
.c('field', { .c('field', {
'label': 'Roles and Affiliations that May Retrieve Member List', 'label': 'Enable Public Logging?',
'type': 'list-multi', 'type': 'boolean',
'var': 'muc#roomconfig_getmemberlist'}) 'var': 'muc#roomconfig_enablelogging'})
.c('value').t('moderator').up() .c('value').t(0).up().up()
.c('value').t('participant').up() .c('field', {
.c('value').t('visitor').up() 'label': 'Allow Occupants to Change Subject?',
.c('option', {'label': 'Moderator'}) 'type': 'boolean',
.c('value').t('moderator').up().up() 'var': 'muc#roomconfig_changesubject'})
.c('option', {'label': 'Participant'}) .c('value').t(0).up().up()
.c('value').t('participant').up().up() .c('field', {
.c('option', {'label': 'Visitor'}) 'label': 'Allow Occupants to Invite Others?',
.c('value').t('visitor').up().up().up() 'type': 'boolean',
.c('field', { 'var': 'muc#roomconfig_allowinvites'})
'label': 'Make Room Publicly Searchable?', .c('value').t(0).up().up()
'type': 'boolean', .c('field', {
'var': 'muc#roomconfig_publicroom'}) 'label': 'Who Can Send Private Messages?',
.c('value').t(0).up().up() 'type': 'list-single',
.c('field', { 'var': 'muc#roomconfig_allowpm'})
'label': 'Make Room Publicly Searchable?', .c('value').t('anyone').up()
'type': 'boolean', .c('option', {'label': 'Anyone'})
'var': 'muc#roomconfig_publicroom'}) .c('value').t('anyone').up().up()
.c('value').t(0).up().up() .c('option', {'label': 'Anyone with Voice'})
.c('field', { .c('value').t('participants').up().up()
'label': 'Make Room Persistent?', .c('option', {'label': 'Moderators Only'})
'type': 'boolean', .c('value').t('moderators').up().up()
'var': 'muc#roomconfig_persistentroom'}) .c('option', {'label': 'Nobody'})
.c('value').t(0).up().up() .c('value').t('none').up().up().up()
.c('field', { .c('field', {
'label': 'Make Room Moderated?', 'label': 'Roles for which Presence is Broadcasted',
'type': 'boolean', 'type': 'list-multi',
'var': 'muc#roomconfig_moderatedroom'}) 'var': 'muc#roomconfig_presencebroadcast'})
.c('value').t(0).up().up() .c('value').t('moderator').up()
.c('field', { .c('value').t('participant').up()
'label': 'Make Room Members Only?', .c('value').t('visitor').up()
'type': 'boolean', .c('option', {'label': 'Moderator'})
'var': 'muc#roomconfig_membersonly'}) .c('value').t('moderator').up().up()
.c('value').t(0).up().up() .c('option', {'label': 'Participant'})
.c('field', { .c('value').t('participant').up().up()
'label': 'Password Required for Entry?', .c('option', {'label': 'Visitor'})
'type': 'boolean', .c('value').t('visitor').up().up().up()
'var': 'muc#roomconfig_passwordprotectedroom'}) .c('field', {
.c('value').t(1).up().up() 'label': 'Roles and Affiliations that May Retrieve Member List',
.c('field', {'type': 'fixed'}) 'type': 'list-multi',
.c('value').t('If a password is required to enter this room,'+ 'var': 'muc#roomconfig_getmemberlist'})
'you must specify the password below.').up().up() .c('value').t('moderator').up()
.c('field', { .c('value').t('participant').up()
'label': 'Password', .c('value').t('visitor').up()
'type': 'text-private', .c('option', {'label': 'Moderator'})
'var': 'muc#roomconfig_roomsecret'}) .c('value').t('moderator').up().up()
.c('value').t('cauldronburn'); .c('option', {'label': 'Participant'})
_converse.connection._dataRecv(test_utils.createRequest(config_stanza)); .c('value').t('participant').up().up()
}); .c('option', {'label': 'Visitor'})
waits(50); .c('value').t('visitor').up().up().up()
runs (function () { .c('field', {
expect(view.$('form.chatroom-form').length).toBe(1); 'label': 'Make Room Publicly Searchable?',
expect(view.$('form.chatroom-form fieldset').length).toBe(2); 'type': 'boolean',
var $membersonly = view.$('input[name="muc#roomconfig_membersonly"]'); 'var': 'muc#roomconfig_publicroom'})
expect($membersonly.length).toBe(1); .c('value').t(0).up().up()
expect($membersonly.attr('type')).toBe('checkbox'); .c('field', {
$membersonly.prop('checked', true); 'label': 'Make Room Publicly Searchable?',
'type': 'boolean',
var $moderated = view.$('input[name="muc#roomconfig_moderatedroom"]'); 'var': 'muc#roomconfig_publicroom'})
expect($moderated.length).toBe(1); .c('value').t(0).up().up()
expect($moderated.attr('type')).toBe('checkbox'); .c('field', {
$moderated.prop('checked', true); 'label': 'Make Room Persistent?',
'type': 'boolean',
var $password = view.$('input[name="muc#roomconfig_roomsecret"]'); 'var': 'muc#roomconfig_persistentroom'})
expect($password.length).toBe(1); .c('value').t(0).up().up()
expect($password.attr('type')).toBe('password'); .c('field', {
'label': 'Make Room Moderated?',
var $allowpm = view.$('select[name="muc#roomconfig_allowpm"]'); 'type': 'boolean',
expect($allowpm.length).toBe(1); 'var': 'muc#roomconfig_moderatedroom'})
$allowpm.val('moderators'); .c('value').t(0).up().up()
.c('field', {
var $presencebroadcast = view.$('select[name="muc#roomconfig_presencebroadcast"]'); 'label': 'Make Room Members Only?',
expect($presencebroadcast.length).toBe(1); 'type': 'boolean',
$presencebroadcast.val(['moderator']); 'var': 'muc#roomconfig_membersonly'})
.c('value').t(0).up().up()
view.$('input[type="submit"]').click(); .c('field', {
}); 'label': 'Password Required for Entry?',
waits(50); 'type': 'boolean',
runs (function () { 'var': 'muc#roomconfig_passwordprotectedroom'})
var $sent_stanza = $(sent_IQ.toLocaleString()); .c('value').t(1).up().up()
expect($sent_stanza.find('field[var="muc#roomconfig_membersonly"] value').text()).toBe('1'); .c('field', {'type': 'fixed'})
expect($sent_stanza.find('field[var="muc#roomconfig_moderatedroom"] value').text()).toBe('1'); .c('value').t('If a password is required to enter this room,'+
expect($sent_stanza.find('field[var="muc#roomconfig_allowpm"] value').text()).toBe('moderators'); 'you must specify the password below.').up().up()
expect($sent_stanza.find('field[var="muc#roomconfig_presencebroadcast"] value').text()).toBe('moderator'); .c('field', {
}); 'label': 'Password',
'type': 'text-private',
'var': 'muc#roomconfig_roomsecret'})
.c('value').t('cauldronburn');
_converse.connection._dataRecv(test_utils.createRequest(config_stanza));
expect(view.$('form.chatroom-form').length).toBe(1);
expect(view.$('form.chatroom-form fieldset').length).toBe(2);
var $membersonly = view.$('input[name="muc#roomconfig_membersonly"]');
expect($membersonly.length).toBe(1);
expect($membersonly.attr('type')).toBe('checkbox');
$membersonly.prop('checked', true);
var $moderated = view.$('input[name="muc#roomconfig_moderatedroom"]');
expect($moderated.length).toBe(1);
expect($moderated.attr('type')).toBe('checkbox');
$moderated.prop('checked', true);
var $password = view.$('input[name="muc#roomconfig_roomsecret"]');
expect($password.length).toBe(1);
expect($password.attr('type')).toBe('password');
var $allowpm = view.$('select[name="muc#roomconfig_allowpm"]');
expect($allowpm.length).toBe(1);
$allowpm.val('moderators');
var $presencebroadcast = view.$('select[name="muc#roomconfig_presencebroadcast"]');
expect($presencebroadcast.length).toBe(1);
$presencebroadcast.val(['moderator']);
view.$('input[type="submit"]').click();
var $sent_stanza = $(sent_IQ.toLocaleString());
expect($sent_stanza.find('field[var="muc#roomconfig_membersonly"] value').text()).toBe('1');
expect($sent_stanza.find('field[var="muc#roomconfig_moderatedroom"] value').text()).toBe('1');
expect($sent_stanza.find('field[var="muc#roomconfig_allowpm"] value').text()).toBe('moderators');
expect($sent_stanza.find('field[var="muc#roomconfig_presencebroadcast"] value').text()).toBe('moderator');
})); }));
it("shows users currently present in the room", mock.initConverse(function (_converse) { it("shows users currently present in the room", mock.initConverse(function (_converse) {
...@@ -859,7 +843,7 @@ ...@@ -859,7 +843,7 @@
it("will use the user's reserved nickname, if it exists", mock.initConverse(function (_converse) { it("will use the user's reserved nickname, if it exists", mock.initConverse(function (_converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -877,7 +861,7 @@ ...@@ -877,7 +861,7 @@
_converse.connection._dataRecv(test_utils.createRequest(features_stanza)); _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'join').andCallThrough(); spyOn(view, 'join').and.callThrough();
/* <iq from='hag66@shakespeare.lit/pda' /* <iq from='hag66@shakespeare.lit/pda'
* id='getnick1' * id='getnick1'
...@@ -938,7 +922,7 @@ ...@@ -938,7 +922,7 @@
expect(info_text).toBe('Your nickname has been automatically set to: thirdwitch'); expect(info_text).toBe('Your nickname has been automatically set to: thirdwitch');
})); }));
it("allows the user to invite their roster contacts to enter the chat room", mock.initConverse(function (_converse) { it("allows the user to invite their roster contacts to enter the chat room", mock.initConverseWithAsync(function (done, _converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
test_utils.createContacts(_converse, 'current'); // We need roster contacts, so that we have someone to invite test_utils.createContacts(_converse, 'current'); // We need roster contacts, so that we have someone to invite
// Since we don't actually fetch roster contacts, we need to // Since we don't actually fetch roster contacts, we need to
...@@ -946,7 +930,7 @@ ...@@ -946,7 +930,7 @@
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(window, 'prompt').andCallFake(function () { spyOn(window, 'prompt').and.callFake(function () {
return "Please join!"; return "Please join!";
}); });
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
...@@ -955,12 +939,15 @@ ...@@ -955,12 +939,15 @@
// receiving the features for the room. // receiving the features for the room.
view.model.set('open', 'true'); view.model.set('open', 'true');
spyOn(view, 'directInvite').andCallThrough(); spyOn(view, 'directInvite').and.callThrough();
var $input; var $input;
view.$el.find('.chat-area').remove(); view.$el.find('.chat-area').remove();
$input = view.$el.find('input.invited-contact');
runs (function () { test_utils.waitUntil(function () {
expect($input.length).toBe(1); return view.$el.find('input.invited-contact').length;
}, 300)
.then(function () {
var $input = view.$el.find('input.invited-contact');
expect($input.attr('placeholder')).toBe('Invite'); expect($input.attr('placeholder')).toBe('Invite');
$input.val("Felix"); $input.val("Felix");
var evt; var evt;
...@@ -973,18 +960,16 @@ ...@@ -973,18 +960,16 @@
evt.initCustomEvent('input', false, false, null); evt.initCustomEvent('input', false, false, null);
} }
$input[0].dispatchEvent(evt); $input[0].dispatchEvent(evt);
});
waits(350); // Needed, due to debounce
runs (function () {
var sent_stanza; var sent_stanza;
spyOn(_converse.connection, 'send').andCallFake(function (stanza) { spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
sent_stanza = stanza; sent_stanza = stanza;
}); });
var $hint = $input.siblings('ul').children('li'); var $hint = $input.siblings('ul').children('li');
expect($input.val()).toBe('Felix'); expect($input.val()).toBe('Felix');
expect($hint[0].textContent).toBe('Felix Amsel'); expect($hint[0].textContent).toBe('Felix Amsel');
expect($hint.length).toBe(1); expect($hint.length).toBe(1);
var evt;
if (typeof(Event) === 'function') { if (typeof(Event) === 'function') {
// Not working on PhantomJS // Not working on PhantomJS
evt = new Event('mousedown', {'bubbles': true}); evt = new Event('mousedown', {'bubbles': true});
...@@ -1000,12 +985,13 @@ ...@@ -1000,12 +985,13 @@
"</message>" "</message>"
); );
} }
done();
}); });
})); }));
it("can be joined automatically, based upon a received invite", mock.initConverse(function (_converse) { it("can be joined automatically, based upon a received invite", mock.initConverse(function (_converse) {
test_utils.createContacts(_converse, 'current'); // We need roster contacts, who can invite us test_utils.createContacts(_converse, 'current'); // We need roster contacts, who can invite us
spyOn(window, 'confirm').andCallFake(function () { spyOn(window, 'confirm').and.callFake(function () {
return true; return true;
}); });
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
...@@ -1079,35 +1065,29 @@ ...@@ -1079,35 +1065,29 @@
expect($chat_content.find('.chat-message').length).toBe(1); expect($chat_content.find('.chat-message').length).toBe(1);
expect($chat_content.find('.chat-msg-content').last().text()).toBe(text); expect($chat_content.find('.chat-msg-content').last().text()).toBe(text);
// We don't emit an event if it's our own message // We don't emit an event if it's our own message
expect(_converse.emit.callCount, 1); expect(_converse.emit.calls.count(), 1);
})); }));
it("will cause the chat area to be scrolled down only if it was at the bottom already", mock.initConverse(function (_converse) { it("will cause the chat area to be scrolled down only if it was at the bottom already", mock.initConverseWithAsync(function (done, _converse) {
var message = 'This message is received while the chat area is scrolled up'; var message = 'This message is received while the chat area is scrolled up';
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'scrollDown').andCallThrough(); spyOn(view, 'scrollDown').and.callThrough();
runs(function () { /* Create enough messages so that there's a
/* Create enough messages so that there's a * scrollbar.
* scrollbar. */
*/ for (var i=0; i<20; i++) {
for (var i=0; i<20; i++) { _converse.chatboxes.onMessage(
_converse.chatboxes.onMessage( $msg({
$msg({ from: 'lounge@localhost/someone',
from: 'lounge@localhost/someone', to: 'dummy@localhost.com',
to: 'dummy@localhost.com', type: 'groupchat',
type: 'groupchat', id: (new Date()).getTime(),
id: (new Date()).getTime(), }).c('body').t('Message: '+i).tree());
}).c('body').t('Message: '+i).tree()); }
} // Give enough time for `markScrolled` to have been called
}); setTimeout(function () {
waits(500); // Give enough time for `markScrolled` to have been called
runs(function () {
view.$content.scrollTop(0); view.$content.scrollTop(0);
});
waits(250);
runs(function () {
expect(view.model.get('scrolled')).toBeTruthy();
_converse.chatboxes.onMessage( _converse.chatboxes.onMessage(
$msg({ $msg({
from: 'lounge@localhost/someone', from: 'lounge@localhost/someone',
...@@ -1115,15 +1095,14 @@ ...@@ -1115,15 +1095,14 @@
type: 'groupchat', type: 'groupchat',
id: (new Date()).getTime(), id: (new Date()).getTime(),
}).c('body').t(message).tree()); }).c('body').t(message).tree());
});
waits(150);
runs(function () {
// Now check that the message appears inside the chatbox in the DOM // Now check that the message appears inside the chatbox in the DOM
var $chat_content = view.$el.find('.chat-content'); var $chat_content = view.$el.find('.chat-content');
var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text(); var msg_txt = $chat_content.find('.chat-message:last').find('.chat-msg-content').text();
expect(msg_txt).toEqual(message); expect(msg_txt).toEqual(message);
expect(view.$content.scrollTop()).toBe(0); expect(view.$content.scrollTop()).toBe(0);
}); done();
}, 500);
})); }));
it("shows received chatroom subject messages", mock.initConverse(function (_converse) { it("shows received chatroom subject messages", mock.initConverse(function (_converse) {
...@@ -1267,7 +1246,7 @@ ...@@ -1267,7 +1246,7 @@
it("queries for the room information before attempting to join the user", mock.initConverse(function (_converse) { it("queries for the room information before attempting to join the user", mock.initConverse(function (_converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -1383,7 +1362,7 @@ ...@@ -1383,7 +1362,7 @@
it("indicates when a room is no longer anonymous", mock.initConverse(function (_converse) { it("indicates when a room is no longer anonymous", mock.initConverse(function (_converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -1496,57 +1475,52 @@ ...@@ -1496,57 +1475,52 @@
_converse.rosterview.render(); _converse.rosterview.render();
})); }));
it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'", mock.initConverse(function (_converse) { it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'", mock.initConverseWithAsync(function (done, _converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var view = _converse.chatboxviews.get('lounge@localhost'), var view = _converse.chatboxviews.get('lounge@localhost'),
trimmed_chatboxes = _converse.minimized_chats; trimmed_chatboxes = _converse.minimized_chats;
spyOn(view, 'minimize').andCallThrough(); spyOn(view, 'minimize').and.callThrough();
spyOn(view, 'maximize').andCallThrough(); spyOn(view, 'maximize').and.callThrough();
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
runs(function () { view.$el.find('.toggle-chatbox-button').click();
view.$el.find('.toggle-chatbox-button').click();
}); expect(view.minimize).toHaveBeenCalled();
waits(350); expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object));
runs(function () { expect(view.$el.is(':visible')).toBeFalsy();
expect(view.minimize).toHaveBeenCalled(); expect(view.model.get('minimized')).toBeTruthy();
expect(_converse.emit).toHaveBeenCalledWith('chatBoxMinimized', jasmine.any(Object)); expect(view.minimize).toHaveBeenCalled();
expect(view.$el.is(':visible')).toBeFalsy(); var trimmedview = trimmed_chatboxes.get(view.model.get('id'));
expect(view.model.get('minimized')).toBeTruthy(); trimmedview.$("a.restore-chat").click();
expect(view.minimize).toHaveBeenCalled();
var trimmedview = trimmed_chatboxes.get(view.model.get('id')); test_utils.waitUntil(function () {
trimmedview.$("a.restore-chat").click(); return view.$el.is(':visible');
}); }, 300)
waits(350); .then(function () {
runs(function () {
expect(view.maximize).toHaveBeenCalled(); expect(view.maximize).toHaveBeenCalled();
expect(_converse.emit).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('chatBoxMaximized', jasmine.any(Object));
expect(view.$el.is(':visible')).toBeTruthy(); expect(view.$el.is(':visible')).toBeTruthy();
expect(view.model.get('minimized')).toBeFalsy(); expect(view.model.get('minimized')).toBeFalsy();
expect(_converse.emit.callCount, 3); expect(_converse.emit.calls.count(), 3);
done();
}); });
})); }));
it("can be closed again by clicking a DOM element with class 'close-chatbox-button'", mock.initConverse(function (_converse) { it("can be closed again by clicking a DOM element with class 'close-chatbox-button'", mock.initConverse(function (_converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'close').andCallThrough(); spyOn(view, 'close').and.callThrough();
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(view, 'leave'); spyOn(view, 'leave');
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
runs(function () { view.$el.find('.close-chatbox-button').click();
view.$el.find('.close-chatbox-button').click(); expect(view.close).toHaveBeenCalled();
}); expect(view.leave).toHaveBeenCalled();
waits(50); // XXX: After refactoring, the chat box only gets closed
runs(function () { // once we have confirmation from the server. To test this,
expect(view.close).toHaveBeenCalled(); // we would have to mock the returned presence stanza.
expect(view.leave).toHaveBeenCalled(); // See the "leave" method on the ChatRoomView.
// XXX: After refactoring, the chat box only gets closed // expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
// once we have confirmation from the server. To test this,
// we would have to mock the returned presence stanza.
// See the "leave" method on the ChatRoomView.
// expect(_converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
});
})); }));
}); });
...@@ -1557,9 +1531,9 @@ ...@@ -1557,9 +1531,9 @@
var sent_stanza; var sent_stanza;
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'onMessageSubmitted').andCallThrough(); spyOn(view, 'onMessageSubmitted').and.callThrough();
spyOn(view, 'clearChatRoomMessages'); spyOn(view, 'clearChatRoomMessages');
spyOn(_converse.connection, 'send').andCallFake(function (stanza) { spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
sent_stanza = stanza; sent_stanza = stanza;
}); });
// Check the alias /topic // Check the alias /topic
...@@ -1590,7 +1564,7 @@ ...@@ -1590,7 +1564,7 @@
it("to clear messages", mock.initConverse(function (_converse) { it("to clear messages", mock.initConverse(function (_converse) {
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'onMessageSubmitted').andCallThrough(); spyOn(view, 'onMessageSubmitted').and.callThrough();
spyOn(view, 'clearChatRoomMessages'); spyOn(view, 'clearChatRoomMessages');
view.$el.find('.chat-textarea').text('/clear'); view.$el.find('.chat-textarea').text('/clear');
view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13})); view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
...@@ -1601,16 +1575,16 @@ ...@@ -1601,16 +1575,16 @@
it("to make a user an owner", mock.initConverse(function (_converse) { it("to make a user an owner", mock.initConverse(function (_converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'onMessageSubmitted').andCallThrough(); spyOn(view, 'onMessageSubmitted').and.callThrough();
spyOn(view, 'setAffiliation').andCallThrough(); spyOn(view, 'setAffiliation').and.callThrough();
spyOn(view, 'showStatusNotification').andCallThrough(); spyOn(view, 'showStatusNotification').and.callThrough();
spyOn(view, 'validateRoleChangeCommand').andCallThrough(); spyOn(view, 'validateRoleChangeCommand').and.callThrough();
view.$el.find('.chat-textarea').text('/owner'); view.$el.find('.chat-textarea').text('/owner');
view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13})); view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
expect(view.onMessageSubmitted).toHaveBeenCalled(); expect(view.onMessageSubmitted).toHaveBeenCalled();
...@@ -1626,8 +1600,8 @@ ...@@ -1626,8 +1600,8 @@
// again via triggering Event doesn't work for some weird // again via triggering Event doesn't work for some weird
// reason. // reason.
view.onMessageSubmitted('/owner annoyingGuy@localhost You\'re annoying'); view.onMessageSubmitted('/owner annoyingGuy@localhost You\'re annoying');
expect(view.validateRoleChangeCommand.callCount).toBe(2); expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
expect(view.showStatusNotification.callCount).toBe(1); expect(view.showStatusNotification.calls.count()).toBe(1);
expect(view.setAffiliation).toHaveBeenCalled(); expect(view.setAffiliation).toHaveBeenCalled();
// Check that the member list now gets updated // Check that the member list now gets updated
expect(sent_IQ.toLocaleString()).toBe( expect(sent_IQ.toLocaleString()).toBe(
...@@ -1643,16 +1617,16 @@ ...@@ -1643,16 +1617,16 @@
it("to ban a user", mock.initConverse(function (_converse) { it("to ban a user", mock.initConverse(function (_converse) {
var sent_IQ, IQ_id; var sent_IQ, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(_converse, 'lounge', 'localhost', 'dummy');
var view = _converse.chatboxviews.get('lounge@localhost'); var view = _converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'onMessageSubmitted').andCallThrough(); spyOn(view, 'onMessageSubmitted').and.callThrough();
spyOn(view, 'setAffiliation').andCallThrough(); spyOn(view, 'setAffiliation').and.callThrough();
spyOn(view, 'showStatusNotification').andCallThrough(); spyOn(view, 'showStatusNotification').and.callThrough();
spyOn(view, 'validateRoleChangeCommand').andCallThrough(); spyOn(view, 'validateRoleChangeCommand').and.callThrough();
view.$el.find('.chat-textarea').text('/ban'); view.$el.find('.chat-textarea').text('/ban');
view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13})); view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
expect(view.onMessageSubmitted).toHaveBeenCalled(); expect(view.onMessageSubmitted).toHaveBeenCalled();
...@@ -1667,8 +1641,8 @@ ...@@ -1667,8 +1641,8 @@
// again via triggering Event doesn't work for some weird // again via triggering Event doesn't work for some weird
// reason. // reason.
view.onMessageSubmitted('/ban annoyingGuy@localhost You\'re annoying'); view.onMessageSubmitted('/ban annoyingGuy@localhost You\'re annoying');
expect(view.validateRoleChangeCommand.callCount).toBe(2); expect(view.validateRoleChangeCommand.calls.count()).toBe(2);
expect(view.showStatusNotification.callCount).toBe(1); expect(view.showStatusNotification.calls.count()).toBe(1);
expect(view.setAffiliation).toHaveBeenCalled(); expect(view.setAffiliation).toHaveBeenCalled();
// Check that the member list now gets updated // Check that the member list now gets updated
expect(sent_IQ.toLocaleString()).toBe( expect(sent_IQ.toLocaleString()).toBe(
...@@ -1707,17 +1681,13 @@ ...@@ -1707,17 +1681,13 @@
.c('not-authorized').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('not-authorized').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'renderPasswordForm').andCallThrough(); spyOn(view, 'renderPasswordForm').and.callThrough();
runs(function () { view.onChatRoomPresence(presence);
view.onChatRoomPresence(presence);
}); var $chat_body = view.$el.find('.chatroom-body');
waits(250); expect(view.renderPasswordForm).toHaveBeenCalled();
runs(function () { expect($chat_body.find('form.chatroom-form').length).toBe(1);
var $chat_body = view.$el.find('.chatroom-body'); expect($chat_body.find('legend').text()).toBe('This chatroom requires a password');
expect(view.renderPasswordForm).toHaveBeenCalled();
expect($chat_body.find('form.chatroom-form').length).toBe(1);
expect($chat_body.find('legend').text()).toBe('This chatroom requires a password');
});
})); }));
it("will show an error message if the room is members-only and the user not included", mock.initConverse(function (_converse) { it("will show an error message if the room is members-only and the user not included", mock.initConverse(function (_converse) {
...@@ -1731,7 +1701,7 @@ ...@@ -1731,7 +1701,7 @@
.c('error').attrs({by:'lounge@localhost', type:'auth'}) .c('error').attrs({by:'lounge@localhost', type:'auth'})
.c('registration-required').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('registration-required').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
view.onChatRoomPresence(presence); view.onChatRoomPresence(presence);
expect(view.$el.find('.chatroom-body p:last').text()).toBe('You are not on the member list of this room'); expect(view.$el.find('.chatroom-body p:last').text()).toBe('You are not on the member list of this room');
})); }));
...@@ -1747,7 +1717,7 @@ ...@@ -1747,7 +1717,7 @@
.c('error').attrs({by:'lounge@localhost', type:'auth'}) .c('error').attrs({by:'lounge@localhost', type:'auth'})
.c('forbidden').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('forbidden').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
view.onChatRoomPresence(presence); view.onChatRoomPresence(presence);
expect(view.$el.find('.chatroom-body p:last').text()).toBe('You have been banned from this room'); expect(view.$el.find('.chatroom-body p:last').text()).toBe('You have been banned from this room');
})); }));
...@@ -1763,7 +1733,7 @@ ...@@ -1763,7 +1733,7 @@
.c('error').attrs({by:'lounge@localhost', type:'cancel'}) .c('error').attrs({by:'lounge@localhost', type:'cancel'})
.c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
view.onChatRoomPresence(presence); view.onChatRoomPresence(presence);
expect(view.$el.find('.chatroom-body form.chatroom-form label:first').text()).toBe('Please choose your nickname'); expect(view.$el.find('.chatroom-body form.chatroom-form label:first').text()).toBe('Please choose your nickname');
})); }));
...@@ -1795,8 +1765,8 @@ ...@@ -1795,8 +1765,8 @@
.c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
spyOn(view, 'join').andCallThrough(); spyOn(view, 'join').and.callThrough();
// Simulate repeatedly that there's already someone in the room // Simulate repeatedly that there's already someone in the room
// with that nickname // with that nickname
...@@ -1832,7 +1802,7 @@ ...@@ -1832,7 +1802,7 @@
.c('error').attrs({by:'lounge@localhost', type:'cancel'}) .c('error').attrs({by:'lounge@localhost', type:'cancel'})
.c('not-allowed').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('not-allowed').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
view.onChatRoomPresence(presence); view.onChatRoomPresence(presence);
expect(view.$el.find('.chatroom-body p:last').text()).toBe('You are not allowed to create new rooms'); expect(view.$el.find('.chatroom-body p:last').text()).toBe('You are not allowed to create new rooms');
})); }));
...@@ -1848,7 +1818,7 @@ ...@@ -1848,7 +1818,7 @@
.c('error').attrs({by:'lounge@localhost', type:'cancel'}) .c('error').attrs({by:'lounge@localhost', type:'cancel'})
.c('not-acceptable').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('not-acceptable').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
view.onChatRoomPresence(presence); view.onChatRoomPresence(presence);
expect(view.$el.find('.chatroom-body p:last').text()).toBe("Your nickname doesn't conform to this room's policies"); expect(view.$el.find('.chatroom-body p:last').text()).toBe("Your nickname doesn't conform to this room's policies");
})); }));
...@@ -1864,7 +1834,7 @@ ...@@ -1864,7 +1834,7 @@
.c('error').attrs({by:'lounge@localhost', type:'cancel'}) .c('error').attrs({by:'lounge@localhost', type:'cancel'})
.c('item-not-found').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('item-not-found').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
view.onChatRoomPresence(presence); view.onChatRoomPresence(presence);
expect(view.$el.find('.chatroom-body p:last').text()).toBe("This room does not (yet) exist"); expect(view.$el.find('.chatroom-body p:last').text()).toBe("This room does not (yet) exist");
})); }));
...@@ -1880,7 +1850,7 @@ ...@@ -1880,7 +1850,7 @@
.c('error').attrs({by:'lounge@localhost', type:'cancel'}) .c('error').attrs({by:'lounge@localhost', type:'cancel'})
.c('service-unavailable').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree; .c('service-unavailable').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
var view = _converse.chatboxviews.get('problematic@muc.localhost'); var view = _converse.chatboxviews.get('problematic@muc.localhost');
spyOn(view, 'showErrorMessage').andCallThrough(); spyOn(view, 'showErrorMessage').and.callThrough();
view.onChatRoomPresence(presence); view.onChatRoomPresence(presence);
expect(view.$el.find('.chatroom-body p:last').text()).toBe("This room has reached its maximum number of occupants"); expect(view.$el.find('.chatroom-body p:last').text()).toBe("This room has reached its maximum number of occupants");
})); }));
...@@ -1891,7 +1861,7 @@ ...@@ -1891,7 +1861,7 @@
it("will first be added to the member list if the chat room is members only", mock.initConverse(function (_converse) { it("will first be added to the member list if the chat room is members only", mock.initConverse(function (_converse) {
var sent_IQs = [], IQ_ids = []; var sent_IQs = [], IQ_ids = [];
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQs.push(iq); sent_IQs.push(iq);
IQ_ids.push(sendIQ.bind(this)(iq, callback, errback)); IQ_ids.push(sendIQ.bind(this)(iq, callback, errback));
}); });
...@@ -1924,7 +1894,7 @@ ...@@ -1924,7 +1894,7 @@
var sent_stanza, var sent_stanza,
sent_id; sent_id;
spyOn(_converse.connection, 'send').andCallFake(function (stanza) { spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
if (stanza.nodeTree && stanza.nodeTree.nodeName === 'message') { if (stanza.nodeTree && stanza.nodeTree.nodeName === 'message') {
sent_id = stanza.nodeTree.getAttribute('id'); sent_id = stanza.nodeTree.getAttribute('id');
sent_stanza = stanza; sent_stanza = stanza;
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils"], factory); define(["mock", "converse-core", "test-utils"], factory);
} (this, function (mock, converse, test_utils) { } (this, function (mock, converse, test_utils) {
var _ = converse.env._; var _ = converse.env._;
var $ = converse.env.jQuery; var $ = converse.env.jQuery;
...@@ -25,24 +25,19 @@ ...@@ -25,24 +25,19 @@
describe("The Control Box", function () { describe("The Control Box", function () {
it("can be opened by clicking a DOM element with class 'toggle-controlbox'", mock.initConverse(function (_converse) { 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
// This spec will only pass if the controlbox is not currently // open yet.
// open yet. expect($("div#controlbox").is(':visible')).toBe(false);
expect($("div#controlbox").is(':visible')).toBe(false); spyOn(_converse.controlboxtoggle, 'onClick').and.callThrough();
spyOn(_converse.controlboxtoggle, 'onClick').andCallThrough(); spyOn(_converse.controlboxtoggle, 'showControlBox').and.callThrough();
spyOn(_converse.controlboxtoggle, 'showControlBox').andCallThrough(); spyOn(_converse, 'emit');
spyOn(_converse, 'emit'); // Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick')
// Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick') _converse.controlboxtoggle.delegateEvents();
_converse.controlboxtoggle.delegateEvents(); $('.toggle-controlbox').click();
$('.toggle-controlbox').click(); expect(_converse.controlboxtoggle.onClick).toHaveBeenCalled();
}.bind(_converse)); expect(_converse.controlboxtoggle.showControlBox).toHaveBeenCalled();
waits(50); expect(_converse.emit).toHaveBeenCalledWith('controlBoxOpened', jasmine.any(Object));
runs(function () { expect($("div#controlbox").is(':visible')).toBe(true);
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 () { describe("The Status Widget", function () {
...@@ -57,37 +52,29 @@ ...@@ -57,37 +52,29 @@
it("can be used to set the current user's chat status", mock.initConverse(function (_converse) { it("can be used to set the current user's chat status", mock.initConverse(function (_converse) {
test_utils.openControlBox(); test_utils.openControlBox();
var view = _converse.xmppstatusview; var view = _converse.xmppstatusview;
spyOn(view, 'toggleOptions').andCallThrough(); spyOn(view, 'toggleOptions').and.callThrough();
spyOn(view, 'setStatus').andCallThrough(); spyOn(view, 'setStatus').and.callThrough();
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called 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();
view.$el.find('a.choose-xmpp-status').click(); expect(view.toggleOptions).toHaveBeenCalled();
expect(view.toggleOptions).toHaveBeenCalled(); spyOn(view, 'updateStatusUI').and.callThrough();
}); view.initialize(); // Rebind events for spy
waits(250); $(view.$el.find('.dropdown dd ul li a')[1]).click(); // Change status to "dnd"
runs(function () { expect(view.setStatus).toHaveBeenCalled();
spyOn(view, 'updateStatusUI').andCallThrough(); expect(_converse.emit).toHaveBeenCalledWith('statusChanged', 'dnd');
view.initialize(); // Rebind events for spy expect(view.updateStatusUI).toHaveBeenCalled();
$(view.$el.find('.dropdown dd ul li a')[1]).click(); // Change status to "dnd" expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(false);
expect(view.setStatus).toHaveBeenCalled(); expect(view.$el.find('a.choose-xmpp-status').hasClass('dnd')).toBe(true);
expect(_converse.emit).toHaveBeenCalledWith('statusChanged', 'dnd'); expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am busy');
});
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) { it("can be used to set a custom status message", mock.initConverse(function (_converse) {
test_utils.openControlBox(); test_utils.openControlBox();
var view = _converse.xmppstatusview; var view = _converse.xmppstatusview;
_converse.xmppstatus.save({'status': 'online'}); _converse.xmppstatus.save({'status': 'online'});
spyOn(view, 'setStatusMessage').andCallThrough(); spyOn(view, 'setStatusMessage').and.callThrough();
spyOn(view, 'renderStatusChangeForm').andCallThrough(); spyOn(view, 'renderStatusChangeForm').and.callThrough();
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
view.$el.find('a.change-xmpp-status-message').click(); view.$el.find('a.change-xmpp-status-message').click();
...@@ -95,17 +82,12 @@ ...@@ -95,17 +82,12 @@
// The async testing here is used only to provide time for // The async testing here is used only to provide time for
// visual feedback // visual feedback
var msg = 'I am happy'; var msg = 'I am happy';
runs (function () { view.$el.find('form input.custom-xmpp-status').val(msg);
view.$el.find('form input.custom-xmpp-status').val(msg); view.$el.find('form#set-custom-xmpp-status').submit();
}); expect(view.setStatusMessage).toHaveBeenCalled();
waits(250); expect(_converse.emit).toHaveBeenCalledWith('statusMessageChanged', msg);
runs (function () { expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
view.$el.find('form#set-custom-xmpp-status').submit(); expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe(msg);
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);
});
})); }));
}); });
}); });
...@@ -114,17 +96,15 @@ ...@@ -114,17 +96,15 @@
describe("The live filter", function () { describe("The live filter", function () {
it("will only appear when roster contacts flow over the visible area", mock.initConverse(function (_converse) { it("will only appear when roster contacts flow over the visible area", mock.initConverseWithAsync(function (done, _converse) {
var $filter = _converse.rosterview.$('.roster-filter'); var $filter = _converse.rosterview.$('.roster-filter');
var names = mock.cur_names; var names = mock.cur_names;
runs(function () { test_utils.openControlBox();
test_utils.openControlBox(); _converse.rosterview.update(); // XXX: Will normally called as event handler
_converse.rosterview.update(); // XXX: Will normally called as event handler expect($filter.length).toBe(1);
}); test_utils.waitUntil(function () {
waits(5); // Needed, due to debounce return !$filter.is(':visible');
runs(function () { }).then(function () {
expect($filter.length).toBe(1);
expect($filter.is(':visible')).toBeFalsy();
for (var i=0; i<names.length; i++) { for (var i=0; i<names.length; i++) {
_converse.roster.create({ _converse.roster.create({
ask: null, ask: null,
...@@ -135,203 +115,193 @@ ...@@ -135,203 +115,193 @@
}); });
_converse.rosterview.update(); // XXX: Will normally called as event handler _converse.rosterview.update(); // XXX: Will normally called as event handler
} }
}); test_utils.waitUntil(function () {
waits(5); // Needed, due to debounce if (_converse.rosterview.$roster.hasScrollBar()) {
runs(function () { return $filter.is(':visible');
$filter = _converse.rosterview.$('.roster-filter'); } else {
if (_converse.rosterview.$roster.hasScrollBar()) { return !$filter.is(':visible');
expect($filter.is(':visible')).toBeTruthy(); }
} else { }).then(function () {
expect($filter.is(':visible')).toBeFalsy(); done();
} });
}); });
})); }));
it("can be used to filter the contacts shown", mock.initConverse(function (_converse) { it("can be used to filter the contacts shown", mock.initConverseWithAsync(function (done, _converse) {
var $filter; var $filter;
var $roster; var $roster;
runs(function () { _converse.roster_groups = true;
_converse.roster_groups = true; test_utils.openControlBox();
test_utils.openControlBox(); test_utils.createGroupedContacts(_converse);
}); $filter = _converse.rosterview.$('.roster-filter');
waits(50); $roster = _converse.rosterview.$roster;
runs(function () { _converse.rosterview.filter_view.delegateEvents();
test_utils.createGroupedContacts(_converse);
$filter = _converse.rosterview.$('.roster-filter'); var promise = test_utils.waitUntil(function () {
$roster = _converse.rosterview.$roster; return $roster.find('dd:visible').length === 15;
}); }, 500)
waits(5); // Needed, due to debounce in "update" method .then(function (contacts) {
runs(function () {
_converse.rosterview.filter_view.delegateEvents();
expect($roster.find('dd:visible').length).toBe(15);
expect($roster.find('dt:visible').length).toBe(5); expect($roster.find('dt:visible').length).toBe(5);
$filter.val("candice"); $filter.val("candice");
expect($roster.find('dd:visible').length).toBe(15); // because no keydown event
expect($roster.find('dt:visible').length).toBe(5); // ditto
$filter.trigger('keydown'); $filter.trigger('keydown');
});
waits(550); // Needed, due to debounce return test_utils.waitUntil(function () {
runs (function () { return $roster.find('dd:visible').length === 1;
expect($roster.find('dd:visible').length).toBe(1); }, 500);
}).then(function (contacts) {
expect($roster.find('dd:visible').eq(0).text().trim()).toBe('Candice van der Knijff'); expect($roster.find('dd:visible').eq(0).text().trim()).toBe('Candice van der Knijff');
expect($roster.find('dt:visible').length).toBe(1); expect($roster.find('dt:visible').length).toBe(1);
expect($roster.find('dt:visible').eq(0).text()).toBe('colleagues'); expect($roster.find('dt:visible').eq(0).text()).toBe('colleagues');
$filter = _converse.rosterview.$('.roster-filter'); $filter = _converse.rosterview.$('.roster-filter');
$filter.val("an"); $filter.val("an");
$filter.trigger('keydown'); $filter.trigger('keydown');
}); return test_utils.waitUntil(function () {
waits(550); // Needed, due to debounce return $roster.find('dd:visible').length === 5;
runs (function () { }, 500)
expect($roster.find('dd:visible').length).toBe(5); }).then(function (contacts) {
expect($roster.find('dt:visible').length).toBe(4); expect($roster.find('dt:visible').length).toBe(4);
$filter = _converse.rosterview.$('.roster-filter'); $filter = _converse.rosterview.$('.roster-filter');
$filter.val("xxx"); $filter.val("xxx");
$filter.trigger('keydown'); $filter.trigger('keydown');
}); return test_utils.waitUntil(function () {
waits(550); // Needed, due to debounce return $roster.find('dd:visible').length === 0;
runs (function () { }, 500)
expect($roster.find('dd:visible').length).toBe(0); }).then(function () {
expect($roster.find('dt:visible').length).toBe(0); expect($roster.find('dt:visible').length).toBe(0);
$filter = _converse.rosterview.$('.roster-filter'); $filter = _converse.rosterview.$('.roster-filter');
$filter.val(""); // Check that contacts are shown again, when the filter string is cleared. $filter.val(""); // Check that contacts are shown again, when the filter string is cleared.
$filter.trigger('keydown'); $filter.trigger('keydown');
}); return test_utils.waitUntil(function () {
waits(550); // Needed, due to debounce return $roster.find('dd:visible').length === 15;
runs(function () { }, 500)
expect($roster.find('dd:visible').length).toBe(15); }).then(function () {
expect($roster.find('dt:visible').length).toBe(5); expect($roster.find('dt:visible').length).toBe(5);
_converse.roster_groups = false;
done();
}); });
_converse.roster_groups = false;
})); }));
it("can be used to filter the groups shown", mock.initConverse(function (_converse) { it("can be used to filter the groups shown", mock.initConverseWithAsync(function (done, _converse) {
var $filter; var $filter;
var $roster; var $roster;
var $type; var $type;
runs(function () { _converse.roster_groups = true;
_converse.roster_groups = true; test_utils.openControlBox();
test_utils.openControlBox(); test_utils.createGroupedContacts(_converse);
}); _converse.rosterview.filter_view.delegateEvents();
waits(50); // Needed, due to debounce in "update" method $filter = _converse.rosterview.$('.roster-filter');
runs(function () { $roster = _converse.rosterview.$roster;
test_utils.createGroupedContacts(_converse); $type = _converse.rosterview.$('.filter-type');
_converse.rosterview.filter_view.delegateEvents(); $type.val('groups');
$filter = _converse.rosterview.$('.roster-filter'); var promise = test_utils.waitUntil(function () {
$roster = _converse.rosterview.$roster; return $roster.find('dd:visible').length === 15;
$type = _converse.rosterview.$('.filter-type'); }, 500);
$type.val('groups'); promise.then(function () {
});
waits(550); // Needed, due to debounce
runs(function () {
expect($roster.find('dd:visible').length).toBe(15);
expect($roster.find('dt:visible').length).toBe(5); expect($roster.find('dt:visible').length).toBe(5);
$filter.val("colleagues"); $filter.val("colleagues");
});
waits(50); // Needed, due to debounce
runs(function () {
expect($roster.find('dd:visible').length).toBe(15); // because no keydown event
expect($roster.find('dt:visible').length).toBe(5); // ditto
$filter.trigger('keydown'); $filter.trigger('keydown');
}); return test_utils.waitUntil(function () {
waits(550); // Needed, due to debounce return $roster.find('dt:visible').length === 1;
runs (function () { }, 500);
expect($roster.find('dt:visible').length).toBe(1); }).then(function () {
expect($roster.find('dt:visible').eq(0).text()).toBe('colleagues'); expect($roster.find('dt:visible').eq(0).text()).toBe('colleagues');
expect($roster.find('dd:visible').length).toBe(3);
// Check that all contacts under the group are shown // Check that all contacts under the group are shown
expect($roster.find('dt:visible').nextUntil('dt', 'dd:hidden').length).toBe(0); expect($roster.find('dt:visible').nextUntil('dt', 'dd:hidden').length).toBe(0);
$filter = _converse.rosterview.$('.roster-filter'); $filter = _converse.rosterview.$('.roster-filter');
$filter.val("xxx"); $filter.val("xxx").trigger('keydown');
$filter.trigger('keydown'); return test_utils.waitUntil(function () {
}); return $roster.find('dd:visible').length === 0;
waits(550); // Needed, due to debounce }, 700);
runs (function () { }).then(function () {
expect($roster.find('dt:visible').length).toBe(0); expect($roster.find('dt:visible').length).toBe(0);
$filter = _converse.rosterview.$('.roster-filter'); $filter = _converse.rosterview.$('.roster-filter');
$filter.val(""); // Check that groups are shown again, when the filter string is cleared. $filter.val(""); // Check that groups are shown again, when the filter string is cleared.
$filter.trigger('keydown'); $filter.trigger('keydown');
}); return test_utils.waitUntil(function () {
waits(550); // Needed, due to debounce return $roster.find('dd:visible').length === 15;
runs(function () { }, 500);
expect($roster.find('dd:visible').length).toBe(15); }).then(function () {
expect($roster.find('dt:visible').length).toBe(5); expect($roster.find('dt:visible').length).toBe(5);
done();
}); });
_converse.roster_groups = false;
})); }));
it("has a button with which its contents can be cleared", mock.initConverse(function (_converse) { it("has a button with which its contents can be cleared", mock.initConverseWithAsync(function (done, _converse) {
_converse.roster_groups = true; _converse.roster_groups = true;
test_utils.openControlBox();
test_utils.createGroupedContacts(_converse); test_utils.createGroupedContacts(_converse);
var $filter = _converse.rosterview.$('.roster-filter'); var $filter = _converse.rosterview.$('.roster-filter');
runs (function () { _converse.rosterview.filter_view.delegateEvents();
_converse.rosterview.filter_view.delegateEvents(); $filter.val("xxx");
$filter.val("xxx"); $filter.trigger('keydown');
$filter.trigger('keydown'); expect($filter.hasClass("x")).toBeFalsy();
expect($filter.hasClass("x")).toBeFalsy(); $filter = _converse.rosterview.$('.roster-filter');
}); test_utils.waitUntil(function () {
waits(550); // Needed, due to debounce return _converse.rosterview.$('.roster-filter').hasClass("x");
runs (function () { }, 900).then(function () {
$filter = _converse.rosterview.$('.roster-filter'); var $filter = _converse.rosterview.$('.roster-filter');
expect($filter.hasClass("x")).toBeTruthy();
$filter.addClass("onX").click(); $filter.addClass("onX").click();
expect($filter.val()).toBe(""); return test_utils.waitUntil(function () {
return !_converse.rosterview.$('.roster-filter').hasClass("x");
}, 900)
}).then(function () {
expect(document.querySelector('.roster-filter').value).toBe("");
done();
}); });
_converse.roster_groups = false;
})); }));
it("can be used to filter contacts by their chat state", mock.initConverse(function (_converse) { it("can be used to filter contacts by their chat state", mock.initConverseWithAsync(function (done, _converse) {
var $filter; var $filter;
var $roster; var $roster;
_converse.roster_groups = true; _converse.roster_groups = true;
test_utils.createGroupedContacts(_converse); test_utils.createGroupedContacts(_converse);
var jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@localhost'; var jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.roster.get(jid).set('chat_status', 'online'); _converse.roster.get(jid).set('chat_status', 'online');
test_utils.openControlBox();
runs(function () { _converse.rosterview.filter_view.delegateEvents();
test_utils.openControlBox(); var $type = _converse.rosterview.$('.filter-type');
_converse.rosterview.filter_view.delegateEvents(); $type.val('state').trigger('change');
var $type = _converse.rosterview.$('.filter-type'); $filter = _converse.rosterview.$('.state-type');
$type.val('state').trigger('change'); $roster = _converse.rosterview.$roster;
});
waits(300); // Needed, due to debounce in "update" method test_utils.waitUntil(function () {
runs(function () { return $roster.find('dd:visible').length === 15;
$filter = _converse.rosterview.$('.state-type'); }, 500)
$roster = _converse.rosterview.$roster; .then(function () {
expect($roster.find('dd:visible').length).toBe(15);
expect($roster.find('dt:visible').length).toBe(5); expect($roster.find('dt:visible').length).toBe(5);
$filter.val("online"); $filter.val("online");
expect($roster.find('dd:visible').length).toBe(15); // because no change event yet
expect($roster.find('dt:visible').length).toBe(5); // ditto
$filter.trigger('change'); $filter.trigger('change');
}); return test_utils.waitUntil(function () {
waits(550); // Needed, due to debounce return $roster.find('dd:visible').length === 1;
runs (function () { }, 500)
expect($roster.find('dd:visible').length).toBe(1); }).then(function () {
expect($roster.find('dd:visible').eq(0).text().trim()).toBe('Rinse Sommer'); expect($roster.find('dd:visible').eq(0).text().trim()).toBe('Rinse Sommer');
expect($roster.find('dt:visible').length).toBe(1); expect($roster.find('dt:visible').length).toBe(1);
var $type = _converse.rosterview.$('.filter-type'); var $type = _converse.rosterview.$('.filter-type');
$type.val('contacts').trigger('change'); $type.val('contacts').trigger('change');
_converse.roster_groups = false; done();
}); });
})); }));
}); });
describe("A Roster Group", function () { describe("A Roster Group", function () {
it("can be used to organize existing contacts", mock.initConverse(function (_converse) { it("can be used to organize existing contacts", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _converse.roster_groups = true;
_converse.roster_groups = true; spyOn(_converse, 'emit');
spyOn(_converse, 'emit'); spyOn(_converse.rosterview, 'update').and.callThrough();
spyOn(_converse.rosterview, 'update').andCallThrough(); _converse.rosterview.render();
_converse.rosterview.render(); test_utils.createContacts(_converse, 'pending');
test_utils.createContacts(_converse, 'pending'); test_utils.createContacts(_converse, 'requesting');
test_utils.createContacts(_converse, 'requesting'); test_utils.createGroupedContacts(_converse);
test_utils.createGroupedContacts(_converse); // Check that the groups appear alphabetically and that
}); // requesting and pending contacts are last.
waits(50); // Needed, due to debounce test_utils.waitUntil(function () {
runs(function () { return _converse.rosterview.$el.find('dt').length;
// Check that the groups appear alphabetically and that }, 500)
// requesting and pending contacts are last. .then(function () {
var group_titles = $.map(_converse.rosterview.$el.find('dt'), function (o) { return $(o).text().trim(); }); var group_titles = $.map(_converse.rosterview.$el.find('dt'), function (o) { return $(o).text().trim(); });
expect(group_titles).toEqual([ expect(group_titles).toEqual([
"Contact requests", "Contact requests",
...@@ -348,29 +318,29 @@ ...@@ -348,29 +318,29 @@
var names = $.map($contacts, function (o) { return $(o).text().trim(); }); var names = $.map($contacts, function (o) { return $(o).text().trim(); });
expect(names).toEqual(_.clone(names).sort()); expect(names).toEqual(_.clone(names).sort());
}); });
done();
}); });
})); }));
it("can share contacts with other roster groups", mock.initConverse(function (_converse) { it("can share contacts with other roster groups", mock.initConverseWithAsync(function (done, _converse) {
_converse.roster_groups = true; _converse.roster_groups = true;
var groups = ['colleagues', 'friends']; var groups = ['colleagues', 'friends'];
runs(function () { spyOn(_converse, 'emit');
var i=0; spyOn(_converse.rosterview, 'update').and.callThrough();
spyOn(_converse, 'emit'); _converse.rosterview.render();
spyOn(_converse.rosterview, 'update').andCallThrough(); for (var i=0; i<mock.cur_names.length; i++) {
_converse.rosterview.render(); _converse.roster.create({
for (i=0; i<mock.cur_names.length; i++) { jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
_converse.roster.create({ subscription: 'both',
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost', ask: null,
subscription: 'both', groups: groups,
ask: null, fullname: mock.cur_names[i]
groups: groups, });
fullname: mock.cur_names[i] }
}); test_utils.waitUntil(function () {
} return _converse.rosterview.$el.find('dd').length;
}); }, 500)
waits(50); // Needed, due to debounce .then(function () {
runs(function () {
// Check that usernames appear alphabetically per group // Check that usernames appear alphabetically per group
_.each(groups, function (name) { _.each(groups, function (name) {
var $contacts = _converse.rosterview.$('dt.roster-group[data-group="'+name+'"]').nextUntil('dt', 'dd'); var $contacts = _converse.rosterview.$('dt.roster-group[data-group="'+name+'"]').nextUntil('dt', 'dd');
...@@ -378,6 +348,7 @@ ...@@ -378,6 +348,7 @@
expect(names).toEqual(_.clone(names).sort()); expect(names).toEqual(_.clone(names).sort());
expect(names.length).toEqual(mock.cur_names.length); expect(names.length).toEqual(mock.cur_names.length);
}); });
done();
}); });
})); }));
...@@ -418,130 +389,122 @@ ...@@ -418,130 +389,122 @@
test_utils.createContacts(_converse, 'pending').openControlBox().openContactsPanel(_converse); test_utils.createContacts(_converse, 'pending').openControlBox().openContactsPanel(_converse);
} }
it("can be collapsed under their own header", mock.initConverse(function (_converse) { it("can be collapsed under their own header", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dd').length;
waits(50); }, 500)
runs(function () { .then(function () {
checkHeaderToggling.apply(_converse, [_converse.rosterview.get('Pending contacts').$el]); checkHeaderToggling.apply(_converse, [_converse.rosterview.get('Pending contacts').$el]);
done();
}); });
})); }));
it("can be added to the roster", mock.initConverse(function (_converse) { it("can be added to the roster", mock.initConverse(function (_converse) {
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
runs(function () { test_utils.openControlBox();
test_utils.openControlBox(); _converse.roster.create({
_converse.roster.create({ jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', subscription: 'none',
subscription: 'none', ask: 'subscribe',
ask: 'subscribe', fullname: mock.pend_names[0]
fullname: mock.pend_names[0]
});
});
waits(300);
runs(function () {
expect(_converse.rosterview.$el.is(':visible')).toEqual(true);
expect(_converse.rosterview.update).toHaveBeenCalled();
}); });
expect(_converse.rosterview.update).toHaveBeenCalled();
})); }));
it("are shown in the roster when show_only_online_users", mock.initConverse(function (_converse) { it("are shown in the roster when show_only_online_users", mock.initConverseWithAsync(function (done, _converse) {
_converse.show_only_online_users = true; _converse.show_only_online_users = true;
runs(function () { spyOn(_converse.rosterview, 'update').and.callThrough();
_addContacts(_converse); _addContacts(_converse);
}); test_utils.waitUntil(function () {
waits(50); return _converse.rosterview.$el.find('dd').length;
spyOn(_converse.rosterview, 'update').andCallThrough(); }, 500)
runs(function () { .then(function () {
expect(_converse.rosterview.$el.is(':visible')).toEqual(true); expect(_converse.rosterview.$el.is(':visible')).toEqual(true);
expect(_converse.rosterview.update).toHaveBeenCalled(); expect(_converse.rosterview.update).toHaveBeenCalled();
});
waits(300); // Needed, due to debounce
runs (function () {
expect(_converse.rosterview.$el.find('dd:visible').length).toBe(3); expect(_converse.rosterview.$el.find('dd:visible').length).toBe(3);
expect(_converse.rosterview.$el.find('dt:visible').length).toBe(1); expect(_converse.rosterview.$el.find('dt:visible').length).toBe(1);
done();
}); });
_converse.show_only_online_users = false;
})); }));
it("are shown in the roster when hide_offline_users", mock.initConverse(function (_converse) { it("are shown in the roster when hide_offline_users", mock.initConverseWithAsync(function (done, _converse) {
_converse.hide_offline_users = true; _converse.hide_offline_users = true;
runs(function () { spyOn(_converse.rosterview, 'update').and.callThrough();
_addContacts(_converse); _addContacts(_converse);
}); test_utils.waitUntil(function () {
waits(50); return _converse.rosterview.$el.find('dd:visible').length;
spyOn(_converse.rosterview, 'update').andCallThrough(); }, 500)
runs(function () { .then(function () {
expect(_converse.rosterview.$el.is(':visible')).toEqual(true);
expect(_converse.rosterview.update).toHaveBeenCalled(); expect(_converse.rosterview.update).toHaveBeenCalled();
}); expect(_converse.rosterview.$el.is(':visible')).toBe(true);
waits(300); // Needed, due to debounce
runs (function () {
expect(_converse.rosterview.$el.find('dd:visible').length).toBe(3); expect(_converse.rosterview.$el.find('dd:visible').length).toBe(3);
expect(_converse.rosterview.$el.find('dt:visible').length).toBe(1); expect(_converse.rosterview.$el.find('dt:visible').length).toBe(1);
done();
}); });
_converse.hide_offline_users = false;
})); }));
it("can be removed by the user", mock.initConverse(function (_converse) { it("can be removed by the user", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); var name = mock.pend_names[0];
}); var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
waits(50); var contact = _converse.roster.get(jid);
runs(function () {
var name = mock.pend_names[0]; spyOn(window, 'confirm').and.returnValue(true);
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; spyOn(contact, 'unauthorize').and.callFake(function () { return contact; });
var contact = _converse.roster.get(jid); spyOn(contact, 'removeFromRoster');
spyOn(window, 'confirm').andReturn(true); spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
spyOn(contact, 'unauthorize').andCallFake(function () { return contact; }); if (typeof callback === "function") { return callback(); }
spyOn(contact, 'removeFromRoster'); });
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback) { test_utils.waitUntil(function () {
if (typeof callback === "function") { return callback(); } return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length;
}); }, 500)
.then(function () {
_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.parent().siblings('.remove-xmpp-contact').click(); .parent().siblings('.remove-xmpp-contact').click();
return test_utils.waitUntil(function () {
return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length === 0
}, 500)
}).then(function () {
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
expect(contact.removeFromRoster).toHaveBeenCalled(); expect(contact.removeFromRoster).toHaveBeenCalled();
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
expect(_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length).toEqual(0); done();
}); });
})); }));
it("do not have a header if there aren't any", mock.initConverse(function (_converse) { it("do not have a header if there aren't any", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { test_utils.openControlBox();
test_utils.openControlBox(); var name = mock.pend_names[0];
var name = mock.pend_names[0]; _converse.roster.create({
_converse.roster.create({ jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost', subscription: 'none',
subscription: 'none', ask: 'subscribe',
ask: 'subscribe', fullname: name
fullname: name
});
}); });
waits(20); spyOn(window, 'confirm').and.returnValue(true);
runs(function () { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
spyOn(window, 'confirm').andReturn(true); if (typeof callback === "function") { return callback(); }
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback) { });
if (typeof callback === "function") { return callback(); } test_utils.waitUntil(function () {
}); return _converse.rosterview.get('Pending contacts').$el.is(':visible');
expect(_converse.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(true); }, 500)
.then(function () {
_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.parent().siblings('.remove-xmpp-contact').click(); .parent().siblings('.remove-xmpp-contact').click();
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
expect(_converse.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(false); expect(_converse.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(false);
done();
}); });
})); }));
it("will lose their own header once the last one has been removed", mock.initConverse(function (_converse) { it("will lose their own header once the last one has been removed", mock.initConverse(function (_converse) {
_addContacts(_converse); _addContacts(_converse);
var name; var name;
spyOn(window, 'confirm').andReturn(true); spyOn(window, 'confirm').and.returnValue(true);
for (var i=0; i<mock.pend_names.length; i++) { for (var i=0; i<mock.pend_names.length; i++) {
name = mock.pend_names[i]; name = mock.pend_names[i];
_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
...@@ -553,7 +516,7 @@ ...@@ -553,7 +516,7 @@
it("can be added to the roster and they will be sorted alphabetically", mock.initConverse(function (_converse) { it("can be added to the roster and they will be sorted alphabetically", mock.initConverse(function (_converse) {
var i, t; var i, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (i=0; i<mock.pend_names.length; i++) { for (i=0; i<mock.pend_names.length; i++) {
_converse.roster.create({ _converse.roster.create({
jid: mock.pend_names[i].replace(/ /g,'.').toLowerCase() + '@localhost', jid: mock.pend_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
...@@ -575,70 +538,75 @@ ...@@ -575,70 +538,75 @@
test_utils.createContacts(_converse, 'current').openControlBox().openContactsPanel(_converse); test_utils.createContacts(_converse, 'current').openControlBox().openContactsPanel(_converse);
}; };
it("can be collapsed under their own header", mock.initConverse(function (_converse) { it("can be collapsed under their own header", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dd:visible').length;
waits(50); }, 500)
runs(function () { .then(function () {
checkHeaderToggling.apply(_converse, [_converse.rosterview.$el.find('dt.roster-group')]); checkHeaderToggling.apply(_converse, [_converse.rosterview.$el.find('dt.roster-group')]);
done();
}); });
})); }));
it("will be hidden when appearing under a collapsed group", mock.initConverse(function (_converse) { it("will be hidden when appearing under a collapsed group", mock.initConverseWithAsync(function (done, _converse) {
_converse.roster_groups = false; _converse.roster_groups = false;
_addContacts(_converse); _addContacts(_converse);
_converse.rosterview.$el.find('dt.roster-group').find('a.group-toggle').click(); test_utils.waitUntil(function () {
var name = "Max Mustermann"; return _converse.rosterview.$el.find('dd:visible').length;
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; }, 500)
_converse.roster.create({ .then(function () {
ask: null, _converse.rosterview.$el.find('dt.roster-group').find('a.group-toggle').click();
fullname: name, var name = "Max Mustermann";
jid: jid, var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
requesting: false, _converse.roster.create({
subscription: 'both' ask: null,
fullname: name,
jid: jid,
requesting: false,
subscription: 'both'
});
var view = _converse.rosterview.get('My contacts').get(jid);
expect(view.$el.is(':visible')).toBe(false);
done();
}); });
var view = _converse.rosterview.get('My contacts').get(jid);
expect(view.$el.is(':visible')).toBe(false);
})); }));
it("can be added to the roster and they will be sorted alphabetically", mock.initConverse(function (_converse) { it("can be added to the roster and they will be sorted alphabetically", mock.initConverseWithAsync(function (done, _converse) {
var i, t; spyOn(_converse.rosterview, 'update').and.callThrough();
spyOn(_converse.rosterview, 'update').andCallThrough(); for (var i=0; i<mock.cur_names.length; i++) {
runs(function () { _converse.roster.create({
for (i=0; i<mock.cur_names.length; i++) { jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
_converse.roster.create({ subscription: 'both',
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost', ask: null,
subscription: 'both', fullname: mock.cur_names[i]
ask: null, });
fullname: mock.cur_names[i] expect(_converse.rosterview.update).toHaveBeenCalled();
}); }
expect(_converse.rosterview.update).toHaveBeenCalled(); test_utils.waitUntil(function () {
} return _converse.rosterview.$el.find('dd').length;
}); }).then(function () {
waits(10);
runs(function () {
// Check that they are sorted alphabetically // Check that they are sorted alphabetically
t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.offline').find('a.open-chat').text(); var t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.offline').find('a.open-chat').text();
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
done();
}); });
})); }));
it("can be removed by the user", mock.initConverse(function (_converse) { it("can be removed by the user", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dd').length;
waits(50); }, 500)
runs(function () { .then(function () {
var name = mock.cur_names[0]; var name = mock.cur_names[0];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
var contact = _converse.roster.get(jid); var contact = _converse.roster.get(jid);
spyOn(window, 'confirm').andReturn(true); spyOn(window, 'confirm').and.returnValue(true);
spyOn(contact, 'removeFromRoster'); spyOn(contact, 'removeFromRoster');
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
if (typeof callback === "function") { return callback(); } if (typeof callback === "function") { return callback(); }
}); });
_converse.rosterview.$el.find(".open-chat:contains('"+name+"')") _converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
.parent().find('.remove-xmpp-contact').click(); .parent().find('.remove-xmpp-contact').click();
...@@ -646,26 +614,26 @@ ...@@ -646,26 +614,26 @@
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
expect(contact.removeFromRoster).toHaveBeenCalled(); expect(contact.removeFromRoster).toHaveBeenCalled();
expect(_converse.rosterview.$el.find(".open-chat:contains('"+name+"')").length).toEqual(0); expect(_converse.rosterview.$el.find(".open-chat:contains('"+name+"')").length).toEqual(0);
done();
}); });
})); }));
it("do not have a header if there aren't any", mock.initConverseWithAsync(function (done, _converse) {
it("do not have a header if there aren't any", mock.initConverse(function (_converse) {
var name = mock.cur_names[0]; var name = mock.cur_names[0];
var contact; var contact;
runs(function () { contact = _converse.roster.create({
contact = _converse.roster.create({ jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost', subscription: 'both',
subscription: 'both', ask: null,
ask: null, fullname: name
fullname: name
});
}); });
waits(50); test_utils.waitUntil(function () {
runs(function () { return _converse.rosterview.$el.find('dt').length;
spyOn(window, 'confirm').andReturn(true); }, 500)
.then(function () {
spyOn(window, 'confirm').and.returnValue(true);
spyOn(contact, 'removeFromRoster'); spyOn(contact, 'removeFromRoster');
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
if (typeof callback === "function") { return callback(); } if (typeof callback === "function") { return callback(); }
}); });
...@@ -676,18 +644,19 @@ ...@@ -676,18 +644,19 @@
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
expect(contact.removeFromRoster).toHaveBeenCalled(); expect(contact.removeFromRoster).toHaveBeenCalled();
expect(_converse.rosterview.$el.find('dt.roster-group').css('display')).toEqual('none'); expect(_converse.rosterview.$el.find('dt.roster-group').css('display')).toEqual('none');
done();
}); });
})); }));
it("can change their status to online and be sorted alphabetically", mock.initConverse(function (_converse) { it("can change their status to online and be sorted alphabetically", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(50); }, 500)
runs(function () { .then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (var i=0; i<mock.cur_names.length; i++) { for (var i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.roster.get(jid).set('chat_status', 'online'); _converse.roster.get(jid).set('chat_status', 'online');
...@@ -696,18 +665,19 @@ ...@@ -696,18 +665,19 @@
t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.online').find('a.open-chat').text(); t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.online').find('a.open-chat').text();
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
done();
}); });
})); }));
it("can change their status to busy and be sorted alphabetically", mock.initConverse(function (_converse) { it("can change their status to busy and be sorted alphabetically", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(50); }, 500)
runs(function () { .then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (var i=0; i<mock.cur_names.length; i++) { for (var i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.roster.get(jid).set('chat_status', 'dnd'); _converse.roster.get(jid).set('chat_status', 'dnd');
...@@ -716,18 +686,19 @@ ...@@ -716,18 +686,19 @@
t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.dnd').find('a.open-chat').text(); t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.dnd').find('a.open-chat').text();
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
done();
}); });
})); }));
it("can change their status to away and be sorted alphabetically", mock.initConverse(function (_converse) { it("can change their status to away and be sorted alphabetically", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(50); }, 500)
runs(function () { .then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (var i=0; i<mock.cur_names.length; i++) { for (var i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.roster.get(jid).set('chat_status', 'away'); _converse.roster.get(jid).set('chat_status', 'away');
...@@ -736,18 +707,19 @@ ...@@ -736,18 +707,19 @@
t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.away').find('a.open-chat').text(); t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.away').find('a.open-chat').text();
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
done();
}); });
})); }));
it("can change their status to xa and be sorted alphabetically", mock.initConverse(function (_converse) { it("can change their status to xa and be sorted alphabetically", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(50); }, 500)
runs(function () { .then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (var i=0; i<mock.cur_names.length; i++) { for (var i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.roster.get(jid).set('chat_status', 'xa'); _converse.roster.get(jid).set('chat_status', 'xa');
...@@ -756,18 +728,19 @@ ...@@ -756,18 +728,19 @@
t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.xa').find('a.open-chat').text(); t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.xa').find('a.open-chat').text();
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
done();
}); });
})); }));
it("can change their status to unavailable and be sorted alphabetically", mock.initConverse(function (_converse) { it("can change their status to unavailable and be sorted alphabetically", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(50); }, 500)
runs(function () { .then(function () {
var jid, t; var jid, t;
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
for (var i=0; i<mock.cur_names.length; i++) { for (var i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.roster.get(jid).set('chat_status', 'unavailable'); _converse.roster.get(jid).set('chat_status', 'unavailable');
...@@ -776,15 +749,16 @@ ...@@ -776,15 +749,16 @@
t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text(); t = _converse.rosterview.$el.find('dt.roster-group').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text();
expect(t).toEqual(mock.cur_names.slice(0, i+1).sort().join('')); expect(t).toEqual(mock.cur_names.slice(0, i+1).sort().join(''));
} }
done();
}); });
})); }));
it("are ordered according to status: online, busy, away, xa, unavailable, offline", mock.initConverse(function (_converse) { it("are ordered according to status: online, busy, away, xa, unavailable, offline", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { _addContacts(_converse);
_addContacts(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(50); }, 500)
runs(function () { .then(function () {
var i, jid; var i, jid;
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
...@@ -862,6 +836,7 @@ ...@@ -862,6 +836,7 @@
expect($(contacts[i]).hasClass('xa')).toBeFalsy(); expect($(contacts[i]).hasClass('xa')).toBeFalsy();
expect($(contacts[i]).hasClass('unavailable')).toBeFalsy(); expect($(contacts[i]).hasClass('unavailable')).toBeFalsy();
} }
done();
}); });
})); }));
}); });
...@@ -876,107 +851,100 @@ ...@@ -876,107 +851,100 @@
names.push($(item).text().replace(/^\s+|\s+$/g, '')); names.push($(item).text().replace(/^\s+|\s+$/g, ''));
} }
}; };
runs(function () {
test_utils.openContactsPanel(_converse);
});
waits(250);
runs(function () {
spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough();
spyOn(_converse.controlboxtoggle, 'showControlBox').andCallThrough();
for (i=0; i<mock.req_names.length; i++) {
_converse.roster.create({
jid: mock.req_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none',
ask: null,
requesting: true,
fullname: mock.req_names[i]
});
}
});
waits(250);
runs(function () {
expect(_converse.rosterview.update).toHaveBeenCalled();
// Check that they are sorted alphabetically
children = _converse.rosterview.get('Contact requests').$el.siblings('dd.requesting-xmpp-contact').find('span');
names = [];
children.each(addName);
expect(names.join('')).toEqual(mock.req_names.slice(0,mock.req_names.length+1).sort().join(''));
});
}));
it("do not have a header if there aren't any", mock.initConverse(function (_converse) {
test_utils.openContactsPanel(_converse); test_utils.openContactsPanel(_converse);
spyOn(_converse, 'emit');
var name = mock.req_names[0]; spyOn(_converse.rosterview, 'update').and.callThrough();
runs(function () { spyOn(_converse.controlboxtoggle, 'showControlBox').and.callThrough();
spyOn(window, 'confirm').andReturn(true); for (i=0; i<mock.req_names.length; i++) {
_converse.roster.create({ _converse.roster.create({
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost', jid: mock.req_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none', subscription: 'none',
ask: null, ask: null,
requesting: true, requesting: true,
fullname: name fullname: mock.req_names[i]
}); });
}
expect(_converse.rosterview.update).toHaveBeenCalled();
// Check that they are sorted alphabetically
children = _converse.rosterview.get('Contact requests').$el.siblings('dd.requesting-xmpp-contact').find('span');
names = [];
children.each(addName);
expect(names.join('')).toEqual(mock.req_names.slice(0,mock.req_names.length+1).sort().join(''));
}));
it("do not have a header if there aren't any", mock.initConverseWithAsync(function (done, _converse) {
test_utils.openContactsPanel(_converse);
var name = mock.req_names[0];
spyOn(window, 'confirm').and.returnValue(true);
_converse.roster.create({
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none',
ask: null,
requesting: true,
fullname: name
}); });
waits(350); test_utils.waitUntil(function () {
runs(function () { return _converse.rosterview.$el.find('dt').length;
}, 500)
.then(function () {
expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true); expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true);
_converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
.parent().siblings('.request-actions') .parent().siblings('.request-actions')
.find('.decline-xmpp-request').click(); .find('.decline-xmpp-request').click();
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(false); expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(false);
done();
}); });
})); }));
it("can be collapsed under their own header", mock.initConverse(function (_converse) { it("can be collapsed under their own header", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.createContacts(_converse, 'requesting').openControlBox(); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(10); }, 500)
runs(function () { .then(function () {
checkHeaderToggling.apply(_converse, [_converse.rosterview.get('Contact requests').$el]); checkHeaderToggling.apply(_converse, [_converse.rosterview.get('Contact requests').$el]);
done();
}); });
})); }));
it("can have their requests accepted by the user", mock.initConverse(function (_converse) { it("can have their requests accepted by the user", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.createContacts(_converse, 'requesting').openControlBox(); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(10); }, 500)
runs(function () { .then(function () {
// TODO: Testing can be more thorough here, the user is // TODO: Testing can be more thorough here, the user is
// actually not accepted/authorized because of // actually not accepted/authorized because of
// mock_connection. // mock_connection.
var name = mock.req_names.sort()[0]; var name = mock.req_names.sort()[0];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
var contact = _converse.roster.get(jid); var contact = _converse.roster.get(jid);
spyOn(_converse.roster, 'sendContactAddIQ').andCallFake(function (jid, fullname, groups, callback) { spyOn(_converse.roster, 'sendContactAddIQ').and.callFake(function (jid, fullname, groups, callback) {
callback(); callback();
}); });
spyOn(contact, 'authorize').andCallFake(function () { return contact; }); spyOn(contact, 'authorize').and.callFake(function () { return contact; });
_converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
.parent().siblings('.request-actions') .parent().siblings('.request-actions')
.find('.accept-xmpp-request').click(); .find('.accept-xmpp-request').click();
expect(_converse.roster.sendContactAddIQ).toHaveBeenCalled(); expect(_converse.roster.sendContactAddIQ).toHaveBeenCalled();
expect(contact.authorize).toHaveBeenCalled(); expect(contact.authorize).toHaveBeenCalled();
done();
}); });
})); }));
it("can have their requests denied by the user", mock.initConverse(function (_converse) { it("can have their requests denied by the user", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.createContacts(_converse, 'requesting').openControlBox(); test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 500)
.then(function () {
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced. _converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
});
waits(50);
runs(function () {
var name = mock.req_names.sort()[1]; var name = mock.req_names.sort()[1];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost'; var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
var contact = _converse.roster.get(jid); var contact = _converse.roster.get(jid);
spyOn(window, 'confirm').andReturn(true); spyOn(window, 'confirm').and.returnValue(true);
spyOn(contact, 'unauthorize').andCallFake(function () { return contact; }); spyOn(contact, 'unauthorize').and.callFake(function () { return contact; });
_converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')") _converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
.parent().siblings('.request-actions') .parent().siblings('.request-actions')
.find('.decline-xmpp-request').click(); .find('.decline-xmpp-request').click();
...@@ -984,6 +952,7 @@ ...@@ -984,6 +952,7 @@
expect(contact.unauthorize).toHaveBeenCalled(); expect(contact.unauthorize).toHaveBeenCalled();
// There should now be one less contact // There should now be one less contact
expect(_converse.roster.length).toEqual(mock.req_names.length-1); expect(_converse.roster.length).toEqual(mock.req_names.length-1);
done();
}); });
})); }));
...@@ -1052,13 +1021,13 @@ ...@@ -1052,13 +1021,13 @@
} }
})); }));
it("will show fullname and jid properties on tooltip", mock.initConverse(function (_converse) { it("will show fullname and jid properties on tooltip", mock.initConverseWithAsync(function (done, _converse) {
runs(function () { test_utils.createContacts(_converse, 'all').openControlBox();
test_utils.createContacts(_converse, 'all').openControlBox(); test_utils.openContactsPanel(_converse);
test_utils.openContactsPanel(_converse); test_utils.waitUntil(function () {
}); return _converse.rosterview.$el.find('dt').length;
waits(10); }, 500)
runs(function () { .then(function () {
var jid, name, i; var jid, name, i;
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
name = mock.cur_names[i]; name = mock.cur_names[i];
...@@ -1070,9 +1039,9 @@ ...@@ -1070,9 +1039,9 @@
expect(dd_title).toContain(name); expect(dd_title).toContain(name);
expect(dd_title).toContain(jid); expect(dd_title).toContain(jid);
} }
done();
}); });
})); }));
}); });
}); });
...@@ -1080,7 +1049,7 @@ ...@@ -1080,7 +1049,7 @@
it("opens up an add form when you click on it", mock.initConverse(function (_converse) { it("opens up an add form when you click on it", mock.initConverse(function (_converse) {
var panel = _converse.chatboxviews.get('controlbox').contactspanel; var panel = _converse.chatboxviews.get('controlbox').contactspanel;
spyOn(panel, 'toggleContactForm').andCallThrough(); spyOn(panel, 'toggleContactForm').and.callThrough();
panel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called panel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
panel.$el.find('a.toggle-xmpp-contact-form').click(); panel.$el.find('a.toggle-xmpp-contact-form').click();
expect(panel.toggleContactForm).toHaveBeenCalled(); expect(panel.toggleContactForm).toHaveBeenCalled();
...@@ -1088,30 +1057,31 @@ ...@@ -1088,30 +1057,31 @@
panel.$el.find('a.toggle-xmpp-contact-form').click(); panel.$el.find('a.toggle-xmpp-contact-form').click();
})); }));
it("can be used to add contact and it checks for case-sensivity", mock.initConverse(function (_converse) { it("can be used to add contact and it checks for case-sensivity", mock.initConverseWithAsync(function (done, _converse) {
spyOn(_converse, 'emit'); spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').andCallThrough(); spyOn(_converse.rosterview, 'update').and.callThrough();
runs(function () { test_utils.openControlBox();
test_utils.openControlBox(); // Adding two contacts one with Capital initials and one with small initials of same JID (Case sensitive check)
// Adding two contacts one with Capital initials and one with small initials of same JID (Case sensitive check) _converse.roster.create({
_converse.roster.create({ jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', subscription: 'none',
subscription: 'none', ask: 'subscribe',
ask: 'subscribe', fullname: mock.pend_names[0]
fullname: mock.pend_names[0]
});
_converse.roster.create({
jid: mock.pend_names[0].replace(/ /g,'.') + '@localhost',
subscription: 'none',
ask: 'subscribe',
fullname: mock.pend_names[0]
});
}); });
waits(300); _converse.roster.create({
runs(function () { jid: mock.pend_names[0].replace(/ /g,'.') + '@localhost',
subscription: 'none',
ask: 'subscribe',
fullname: mock.pend_names[0]
});
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('dt').length;
}, 500)
.then(function () {
// Checking that only one entry is created because both JID is same (Case sensitive check) // Checking that only one entry is created because both JID is same (Case sensitive check)
expect(_converse.rosterview.$el.find('dd:visible').length).toBe(1); expect(_converse.rosterview.$el.find('dd:visible').length).toBe(1);
expect(_converse.rosterview.update).toHaveBeenCalled(); expect(_converse.rosterview.update).toHaveBeenCalled();
done();
}); });
})); }));
...@@ -1150,7 +1120,7 @@ ...@@ -1150,7 +1120,7 @@
var $panels = cbview.$el.find('.controlbox-panes'); var $panels = cbview.$el.find('.controlbox-panes');
var $contacts = $panels.children().first(); var $contacts = $panels.children().first();
var $chatrooms = $panels.children().last(); var $chatrooms = $panels.children().last();
spyOn(cbview, 'switchTab').andCallThrough(); spyOn(cbview, 'switchTab').and.callThrough();
cbview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called cbview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
$tabs.find('li').last().find('a').click(); // Clicks the chatrooms tab $tabs.find('li').last().find('a').click(); // Clicks the chatrooms tab
expect($contacts.is(':visible')).toBe(false); expect($contacts.is(':visible')).toBe(false);
...@@ -1167,25 +1137,20 @@ ...@@ -1167,25 +1137,20 @@
expect($input.length).toBe(1); expect($input.length).toBe(1);
expect($server.length).toBe(1); expect($server.length).toBe(1);
expect($('.chatroom:visible').length).toBe(0); // There shouldn't be any chatrooms open currently expect($('.chatroom:visible').length).toBe(0); // There shouldn't be any chatrooms open currently
spyOn(roomspanel, 'createChatRoom').andCallThrough(); spyOn(roomspanel, 'createChatRoom').and.callThrough();
spyOn(_converse.ChatRoomView.prototype, 'getRoomFeatures').andCallFake(function () { spyOn(_converse.ChatRoomView.prototype, 'getRoomFeatures').and.callFake(function () {
var deferred = new $.Deferred(); var deferred = new $.Deferred();
deferred.resolve(); deferred.resolve();
return deferred.promise(); return deferred.promise();
}); });
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
runs(function () { $input.val('Lounge');
$input.val('Lounge'); $nick.val('dummy');
$nick.val('dummy'); $server.val('muc.localhost');
$server.val('muc.localhost'); roomspanel.$el.find('form').submit();
roomspanel.$el.find('form').submit(); expect(roomspanel.createChatRoom).toHaveBeenCalled();
expect(roomspanel.createChatRoom).toHaveBeenCalled(); expect($('.chatroom:visible').length).toBe(1); // There should now be an open chatroom
});
waits('250');
runs(function () {
expect($('.chatroom:visible').length).toBe(1); // There should now be an open chatroom
});
})); }));
it("can list rooms publically available on the server", mock.initConverse(function (_converse) { it("can list rooms publically available on the server", mock.initConverse(function (_converse) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
define([ define([
"converse-core", "converse-core",
"mock", "mock",
"test_utils"], factory); "test-utils"], factory);
} (this, function (converse, mock, test_utils) { } (this, function (converse, mock, test_utils) {
var b64_sha1 = converse.env.b64_sha1; var b64_sha1 = converse.env.b64_sha1;
var _ = converse.env._; var _ = converse.env._;
...@@ -52,9 +52,9 @@ ...@@ -52,9 +52,9 @@
describe("A chat state indication", function () { describe("A chat state indication", function () {
it("are sent out when the client becomes or stops being idle", mock.initConverse(function (_converse) { it("are sent out when the client becomes or stops being idle", mock.initConverse(function (_converse) {
spyOn(_converse, 'sendCSI').andCallThrough(); spyOn(_converse, 'sendCSI').and.callThrough();
var sent_stanza; var sent_stanza;
spyOn(_converse.connection, 'send').andCallFake(function (stanza) { spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
sent_stanza = stanza; sent_stanza = stanza;
}); });
var i = 0; var i = 0;
...@@ -298,26 +298,23 @@ ...@@ -298,26 +298,23 @@
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var chatboxview; var chatboxview;
waits('300'); // ChatBox.show() is debounced for 250ms // Test on chat that doesn't exist.
runs(function () { expect(_converse.api.chats.get('non-existing@jabber.org')).toBeFalsy();
// Test on chat that doesn't exist. var box = _converse.api.chats.open(jid);
expect(_converse.api.chats.get('non-existing@jabber.org')).toBeFalsy(); expect(box instanceof Object).toBeTruthy();
var box = _converse.api.chats.open(jid); expect(box.model.get('box_id')).toBe(b64_sha1(jid));
expect(box instanceof Object).toBeTruthy(); expect(
expect(box.model.get('box_id')).toBe(b64_sha1(jid)); _.keys(box),
expect( ['close', 'endOTR', 'focus', 'get', 'initiateOTR', 'is_chatroom', 'maximize', 'minimize', 'open', 'set']
_.keys(box), );
['close', 'endOTR', 'focus', 'get', 'initiateOTR', 'is_chatroom', 'maximize', 'minimize', 'open', 'set'] chatboxview = _converse.chatboxviews.get(jid);
); expect(chatboxview.$el.is(':visible')).toBeTruthy();
chatboxview = _converse.chatboxviews.get(jid); // Test for multiple JIDs
expect(chatboxview.$el.is(':visible')).toBeTruthy(); var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
// Test for multiple JIDs var list = _converse.api.chats.open([jid, jid2]);
var jid2 = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost'; expect(_.isArray(list)).toBeTruthy();
var list = _converse.api.chats.open([jid, jid2]); expect(list[0].model.get('box_id')).toBe(b64_sha1(jid));
expect(_.isArray(list)).toBeTruthy(); expect(list[1].model.get('box_id')).toBe(b64_sha1(jid2));
expect(list[0].model.get('box_id')).toBe(b64_sha1(jid));
expect(list[1].model.get('box_id')).toBe(b64_sha1(jid2));
});
})); }));
}); });
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"jquery", "jquery",
"converse-core", "converse-core",
"mock", "mock",
"test_utils"], factory); "test-utils"], factory);
} (this, function ($, converse, mock, test_utils) { } (this, function ($, converse, mock, test_utils) {
"use strict"; "use strict";
var Strophe = converse.env.Strophe; var Strophe = converse.env.Strophe;
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
describe("Service Discovery", function () { describe("Service Discovery", function () {
describe("Whenever converse.js discovers a new server feature", function () { describe("Whenever converse.js discovers a new server feature", function () {
it("emits the serviceDiscovered event", mock.initConverse(function (_converse) { it("emits the serviceDiscovered event", mock.initConverse(function (_converse) {
spyOn(_converse, 'emit'); sinon.spy(_converse, 'emit');
_converse.features.create({'var': Strophe.NS.MAM}); _converse.features.create({'var': Strophe.NS.MAM});
expect(_converse.emit).toHaveBeenCalled(); expect(_converse.emit.called).toBe(true);
expect(_converse.emit.argsForCall[0][1].get('var')).toBe(Strophe.NS.MAM); expect(_converse.emit.args[0][1].get('var')).toBe(Strophe.NS.MAM);
})); }));
}); });
}); });
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils"], factory); define(["mock", "converse-core", "test-utils"], factory);
} (this, function (mock, converse, test_utils) { } (this, function (mock, converse, test_utils) {
return describe("The _converse Event Emitter", function() { return describe("The _converse Event Emitter", function() {
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback).toHaveBeenCalled(); expect(this.callback).toHaveBeenCalled();
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback.callCount, 2); expect(this.callback.calls.count(), 2);
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback.callCount, 3); expect(this.callback.calls.count(), 3);
})); }));
it("allows you to listen once for an emitted event", mock.initConverse(function (_converse) { it("allows you to listen once for an emitted event", mock.initConverse(function (_converse) {
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback).toHaveBeenCalled(); expect(this.callback).toHaveBeenCalled();
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback.callCount, 1); expect(this.callback.calls.count(), 1);
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback.callCount, 1); expect(this.callback.calls.count(), 1);
})); }));
it("allows you to stop listening or subscribing to an event", mock.initConverse(function (_converse) { it("allows you to stop listening or subscribing to an event", mock.initConverse(function (_converse) {
...@@ -46,15 +46,15 @@ ...@@ -46,15 +46,15 @@
_converse.off('connected', this.callback); _converse.off('connected', this.callback);
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback.callCount, 1); expect(this.callback.calls.count(), 1);
expect(this.anotherCallback.callCount, 2); expect(this.anotherCallback.calls.count(), 2);
_converse.once('connected', this.neverCalled); _converse.once('connected', this.neverCalled);
_converse.off('connected', this.neverCalled); _converse.off('connected', this.neverCalled);
_converse.emit('connected'); _converse.emit('connected');
expect(this.callback.callCount, 1); expect(this.callback.calls.count(), 1);
expect(this.anotherCallback.callCount, 3); expect(this.anotherCallback.calls.count(), 3);
expect(this.neverCalled).not.toHaveBeenCalled(); expect(this.neverCalled).not.toHaveBeenCalled();
})); }));
}); });
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"converse-core", "converse-core",
"utils", "utils",
"mock", "mock",
"test_utils" "test-utils"
], factory); ], factory);
} (this, function ($, converse, utils, mock, test_utils) { } (this, function ($, converse, utils, mock, test_utils) {
"use strict"; "use strict";
...@@ -25,23 +25,18 @@ ...@@ -25,23 +25,18 @@
* </message * </message
*/ */
sinon.spy(utils, 'isHeadlineMessage'); sinon.spy(utils, 'isHeadlineMessage');
runs(function () { var stanza = $msg({
var stanza = $msg({ 'xmlns': 'jabber:client',
'xmlns': 'jabber:client', 'to': 'dummy@localhost',
'to': 'dummy@localhost', 'type': 'chat',
'type': 'chat', 'from': 'gapowa20102106@rds-rostov.ru/Adium',
'from': 'gapowa20102106@rds-rostov.ru/Adium', })
}) .c('nick', {'xmlns': "http://jabber.org/protocol/nick"}).t("-wwdmz").up()
.c('nick', {'xmlns': "http://jabber.org/protocol/nick"}).t("-wwdmz").up() .c('body').t('SORRY FOR THIS ADVERT');
.c('body').t('SORRY FOR THIS ADVERT'); _converse.connection._dataRecv(test_utils.createRequest(stanza));
_converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(utils.isHeadlineMessage.called).toBeTruthy();
}); expect(utils.isHeadlineMessage.returned(false)).toBeTruthy();
waits(250); utils.isHeadlineMessage.restore();
runs(function () {
expect(utils.isHeadlineMessage.called).toBeTruthy();
expect(utils.isHeadlineMessage.returned(false)).toBeTruthy();
utils.isHeadlineMessage.restore();
});
})); }));
it("will open and display headline messages", mock.initConverse(function (_converse) { it("will open and display headline messages", mock.initConverse(function (_converse) {
...@@ -59,53 +54,43 @@ ...@@ -59,53 +54,43 @@
* </message> * </message>
*/ */
sinon.spy(utils, 'isHeadlineMessage'); sinon.spy(utils, 'isHeadlineMessage');
runs(function () { var stanza = $msg({
var stanza = $msg({ 'type': 'headline',
'type': 'headline', 'from': 'notify.example.com',
'from': 'notify.example.com', 'to': 'dummy@localhost',
'to': 'dummy@localhost', 'xml:lang': 'en'
'xml:lang': 'en' })
}) .c('subject').t('SIEVE').up()
.c('subject').t('SIEVE').up() .c('body').t('&lt;juliet@example.com&gt; You got mail.').up()
.c('body').t('&lt;juliet@example.com&gt; You got mail.').up() .c('x', {'xmlns': 'jabber:x:oob'})
.c('x', {'xmlns': 'jabber:x:oob'}) .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
.c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18'); _converse.connection._dataRecv(test_utils.createRequest(stanza));
_converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(
}); _.includes(
waits(250); _converse.chatboxviews.keys(),
runs(function () { 'notify.example.com')
expect( ).toBeTruthy();
_.includes( expect(utils.isHeadlineMessage.called).toBeTruthy();
_converse.chatboxviews.keys(), expect(utils.isHeadlineMessage.returned(true)).toBeTruthy();
'notify.example.com') utils.isHeadlineMessage.restore(); // unwraps
).toBeTruthy();
expect(utils.isHeadlineMessage.called).toBeTruthy();
expect(utils.isHeadlineMessage.returned(true)).toBeTruthy();
utils.isHeadlineMessage.restore(); // unwraps
});
})); }));
it("will not show a headline messages from a full JID if allow_non_roster_messaging is false", mock.initConverse(function (_converse) { it("will not show a headline messages from a full JID if allow_non_roster_messaging is false", mock.initConverse(function (_converse) {
_converse.allow_non_roster_messaging = false; _converse.allow_non_roster_messaging = false;
sinon.spy(utils, 'isHeadlineMessage'); sinon.spy(utils, 'isHeadlineMessage');
runs(function () { var stanza = $msg({
var stanza = $msg({ 'type': 'headline',
'type': 'headline', 'from': 'andre5114@jabber.snc.ru/Spark',
'from': 'andre5114@jabber.snc.ru/Spark', 'to': 'dummy@localhost',
'to': 'dummy@localhost', 'xml:lang': 'en'
'xml:lang': 'en' })
}) .c('nick').t('gpocy').up()
.c('nick').t('gpocy').up() .c('body').t('Здравствуйте друзья');
.c('body').t('Здравствуйте друзья'); _converse.connection._dataRecv(test_utils.createRequest(stanza));
_converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(_.without('controlbox', _converse.chatboxviews.keys()).length).toBe(0);
}); expect(utils.isHeadlineMessage.called).toBeTruthy();
waits(250); expect(utils.isHeadlineMessage.returned(true)).toBeTruthy();
runs(function () { utils.isHeadlineMessage.restore(); // unwraps
expect(_.without('controlbox', _converse.chatboxviews.keys()).length).toBe(0);
expect(utils.isHeadlineMessage.called).toBeTruthy();
expect(utils.isHeadlineMessage.returned(true)).toBeTruthy();
utils.isHeadlineMessage.restore(); // unwraps
});
})); }));
}); });
})); }));
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils"], factory); define(["mock", "converse-core", "test-utils"], factory);
} (this, function (mock, converse, test_utils) { } (this, function (mock, converse, test_utils) {
"use strict"; "use strict";
var _ = converse.env._; var _ = converse.env._;
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
it("can be used to query for all archived messages", mock.initConverse(function (_converse) { it("can be used to query for all archived messages", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
it("can be used to query for all messages to/from a particular JID", mock.initConverse(function (_converse) { it("can be used to query for all messages to/from a particular JID", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
it("can be used to query for all messages in a certain timespan", mock.initConverse(function (_converse) { it("can be used to query for all messages in a certain timespan", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
it("can be used to query for all messages after a certain time", mock.initConverse(function (_converse) { it("can be used to query for all messages after a certain time", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
it("can be used to query for a limited set of results", mock.initConverse(function (_converse) { it("can be used to query for a limited set of results", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -169,7 +169,7 @@ ...@@ -169,7 +169,7 @@
it("can be used to page through results", mock.initConverse(function (_converse) { it("can be used to page through results", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -206,7 +206,7 @@ ...@@ -206,7 +206,7 @@
it("accepts \"before\" with an empty string as value to reverse the order", mock.initConverse(function (_converse) { it("accepts \"before\" with an empty string as value to reverse the order", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -242,7 +242,7 @@ ...@@ -242,7 +242,7 @@
} }
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -280,7 +280,7 @@ ...@@ -280,7 +280,7 @@
} }
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
...@@ -352,7 +352,7 @@ ...@@ -352,7 +352,7 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(callback).toHaveBeenCalled(); expect(callback).toHaveBeenCalled();
var args = callback.argsForCall[0]; var args = callback.calls.argsFor(0);
expect(args[0].length).toBe(2); expect(args[0].length).toBe(2);
expect(args[0][0].outerHTML).toBe(msg1.nodeTree.outerHTML); expect(args[0][0].outerHTML).toBe(msg1.nodeTree.outerHTML);
expect(args[0][1].outerHTML).toBe(msg2.nodeTree.outerHTML); expect(args[0][1].outerHTML).toBe(msg2.nodeTree.outerHTML);
...@@ -370,17 +370,17 @@ ...@@ -370,17 +370,17 @@
it("is set once server support for MAM has been confirmed", mock.initConverse(function (_converse) { it("is set once server support for MAM has been confirmed", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
spyOn(_converse, 'onMAMPreferences').andCallThrough(); spyOn(_converse, 'onMAMPreferences').and.callThrough();
_converse.message_archiving = 'never'; _converse.message_archiving = 'never';
var feature = new _converse.Feature({ var feature = new _converse.Feature({
'var': Strophe.NS.MAM 'var': Strophe.NS.MAM
}); });
spyOn(feature, 'save').andCallFake(feature.set); // Save will complain about a url not being set spyOn(feature, 'save').and.callFake(feature.set); // Save will complain about a url not being set
_converse.features.onFeatureAdded(feature); _converse.features.onFeatureAdded(feature);
expect(_converse.connection.sendIQ).toHaveBeenCalled(); expect(_converse.connection.sendIQ).toHaveBeenCalled();
...@@ -407,7 +407,7 @@ ...@@ -407,7 +407,7 @@
expect(_converse.onMAMPreferences).toHaveBeenCalled(); expect(_converse.onMAMPreferences).toHaveBeenCalled();
expect(_converse.connection.sendIQ.callCount).toBe(2); expect(_converse.connection.sendIQ.calls.count()).toBe(2);
expect(sent_stanza.toString()).toBe( expect(sent_stanza.toString()).toBe(
"<iq type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+ "<iq type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<prefs xmlns='urn:xmpp:mam:0' default='never'>"+ "<prefs xmlns='urn:xmpp:mam:0' default='never'>"+
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils"], factory); define(["mock", "converse-core", "test-utils"], factory);
} (this, function (mock, converse, test_utils) { } (this, function (mock, converse, test_utils) {
var _ = converse.env._; var _ = converse.env._;
var $msg = converse.env.$msg; var $msg = converse.env.$msg;
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils", "utils"], factory); define(["mock", "converse-core", "test-utils", "utils"], factory);
} (this, function (mock, converse, test_utils, utils) { } (this, function (mock, converse, test_utils, utils) {
"use strict"; "use strict";
var _ = converse.env._; var _ = converse.env._;
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
// TODO: not yet testing show_desktop_notifications setting // TODO: not yet testing show_desktop_notifications setting
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
spyOn(_converse, 'showMessageNotification'); spyOn(_converse, 'showMessageNotification');
spyOn(_converse, 'areDesktopNotificationsEnabled').andReturn(true); spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
var message = 'This message will show a desktop notification'; var message = 'This message will show a desktop notification';
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
...@@ -46,8 +46,8 @@ ...@@ -46,8 +46,8 @@
}; };
}; };
} }
spyOn(_converse, 'showMessageNotification').andCallThrough(); spyOn(_converse, 'showMessageNotification').and.callThrough();
spyOn(_converse, 'areDesktopNotificationsEnabled').andReturn(true); spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
var message = 'dummy: This message will show a desktop notification'; var message = 'dummy: This message will show a desktop notification';
var nick = mock.chatroom_names[0], var nick = mock.chatroom_names[0],
...@@ -66,56 +66,46 @@ ...@@ -66,56 +66,46 @@
})); }));
it("is shown for headline messages", mock.initConverse(function (_converse) { it("is shown for headline messages", mock.initConverse(function (_converse) {
spyOn(_converse, 'showMessageNotification').andCallThrough(); spyOn(_converse, 'showMessageNotification').and.callThrough();
spyOn(_converse, 'areDesktopNotificationsEnabled').andReturn(true); spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
runs(function () { var stanza = $msg({
var stanza = $msg({ 'type': 'headline',
'type': 'headline', 'from': 'notify.example.com',
'from': 'notify.example.com', 'to': 'dummy@localhost',
'to': 'dummy@localhost', 'xml:lang': 'en'
'xml:lang': 'en' })
}) .c('subject').t('SIEVE').up()
.c('subject').t('SIEVE').up() .c('body').t('&lt;juliet@example.com&gt; You got mail.').up()
.c('body').t('&lt;juliet@example.com&gt; You got mail.').up() .c('x', {'xmlns': 'jabber:x:oob'})
.c('x', {'xmlns': 'jabber:x:oob'}) .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
.c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18'); _converse.connection._dataRecv(test_utils.createRequest(stanza));
_converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(
}); _.includes(_converse.chatboxviews.keys(),
waits(250); 'notify.example.com')
runs(function () { ).toBeTruthy();
expect( expect(_converse.showMessageNotification).toHaveBeenCalled();
_.includes(_converse.chatboxviews.keys(),
'notify.example.com')
).toBeTruthy();
expect(_converse.showMessageNotification).toHaveBeenCalled();
});
})); }));
it("is not shown for full JID headline messages if allow_non_roster_messaging is false", mock.initConverse(function (_converse) { it("is not shown for full JID headline messages if allow_non_roster_messaging is false", mock.initConverse(function (_converse) {
_converse.allow_non_roster_messaging = false; _converse.allow_non_roster_messaging = false;
spyOn(_converse, 'showMessageNotification').andCallThrough(); spyOn(_converse, 'showMessageNotification').and.callThrough();
spyOn(_converse, 'areDesktopNotificationsEnabled').andReturn(true); spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
runs(function () { var stanza = $msg({
var stanza = $msg({ 'type': 'headline',
'type': 'headline', 'from': 'someone@notify.example.com',
'from': 'someone@notify.example.com', 'to': 'dummy@localhost',
'to': 'dummy@localhost', 'xml:lang': 'en'
'xml:lang': 'en' })
}) .c('subject').t('SIEVE').up()
.c('subject').t('SIEVE').up() .c('body').t('&lt;juliet@example.com&gt; You got mail.').up()
.c('body').t('&lt;juliet@example.com&gt; You got mail.').up() .c('x', {'xmlns': 'jabber:x:oob'})
.c('x', {'xmlns': 'jabber:x:oob'}) .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18');
.c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18'); _converse.connection._dataRecv(test_utils.createRequest(stanza));
_converse.connection._dataRecv(test_utils.createRequest(stanza)); expect(
}); _.includes(_converse.chatboxviews.keys(),
waits(250); 'someone@notify.example.com')
runs(function () { ).toBeFalsy();
expect( expect(_converse.showMessageNotification).not.toHaveBeenCalled();
_.includes(_converse.chatboxviews.keys(),
'someone@notify.example.com')
).toBeFalsy();
expect(_converse.showMessageNotification).not.toHaveBeenCalled();
});
})); }));
it("is shown when a user changes their chat state (if show_chatstate_notifications is true)", mock.initConverse(function (_converse) { it("is shown when a user changes their chat state (if show_chatstate_notifications is true)", mock.initConverse(function (_converse) {
...@@ -123,7 +113,7 @@ ...@@ -123,7 +113,7 @@
_converse.show_chatstate_notifications = true; _converse.show_chatstate_notifications = true;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
spyOn(_converse, 'areDesktopNotificationsEnabled').andReturn(true); spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
spyOn(_converse, 'showChatStateNotification'); spyOn(_converse, 'showChatStateNotification');
var jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; var jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.roster.get(jid).set('chat_status', 'busy'); // This will emit 'contactStatusChanged' _converse.roster.get(jid).set('chat_status', 'busy'); // This will emit 'contactStatusChanged'
...@@ -135,7 +125,7 @@ ...@@ -135,7 +125,7 @@
describe("When a new contact request is received", function () { describe("When a new contact request is received", function () {
it("an HTML5 Notification is received", mock.initConverse(function (_converse) { it("an HTML5 Notification is received", mock.initConverse(function (_converse) {
spyOn(_converse, 'areDesktopNotificationsEnabled').andReturn(true); spyOn(_converse, 'areDesktopNotificationsEnabled').and.returnValue(true);
spyOn(_converse, 'showContactRequestNotification'); spyOn(_converse, 'showContactRequestNotification');
_converse.emit('contactRequest', {'fullname': 'Peter Parker', 'jid': 'peter@parker.com'}); _converse.emit('contactRequest', {'fullname': 'Peter Parker', 'jid': 'peter@parker.com'});
expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled(); expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled();
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils"], factory); define(["mock", "converse-core", "test-utils"], factory);
} (this, function (mock, converse, test_utils) { } (this, function (mock, converse, test_utils) {
var $ = converse.env.jQuery; var $ = converse.env.jQuery;
var Strophe = converse.env.Strophe; var Strophe = converse.env.Strophe;
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
chatbox.set('otr_status', 1); // Set OTR status to UNVERIFIED, to mock an encrypted session chatbox.set('otr_status', 1); // Set OTR status to UNVERIFIED, to mock an encrypted session
chatbox.trigger('sendMessage', new _converse.Message({ message: msgtext })); chatbox.trigger('sendMessage', new _converse.Message({ message: msgtext }));
var $sent = $(_converse.connection.send.argsForCall[0][0].tree()); var $sent = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($sent.find('body').siblings('private').length).toBe(1); expect($sent.find('body').siblings('private').length).toBe(1);
expect($sent.find('private').length).toBe(1); expect($sent.find('private').length).toBe(1);
expect($sent.find('private').attr('xmlns')).toBe('urn:xmpp:carbons:2'); expect($sent.find('private').attr('xmlns')).toBe('urn:xmpp:carbons:2');
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils", "converse-ping"], factory); define(["mock", "converse-core", "test-utils", "converse-ping"], factory);
} (this, function (mock, test_utils) { } (this, function (mock, test_utils) {
"use strict"; "use strict";
...@@ -7,16 +7,16 @@ ...@@ -7,16 +7,16 @@
describe("Ping and pong handlers", function () { describe("Ping and pong handlers", function () {
it("are registered when _converse.js is connected", mock.initConverse(function (_converse) { it("are registered when _converse.js is connected", mock.initConverse(function (_converse) {
spyOn(_converse, 'registerPingHandler').andCallThrough(); spyOn(_converse, 'registerPingHandler').and.callThrough();
spyOn(_converse, 'registerPongHandler').andCallThrough(); spyOn(_converse, 'registerPongHandler').and.callThrough();
_converse.emit('connected'); _converse.emit('connected');
expect(_converse.registerPingHandler).toHaveBeenCalled(); expect(_converse.registerPingHandler).toHaveBeenCalled();
expect(_converse.registerPongHandler).toHaveBeenCalled(); expect(_converse.registerPongHandler).toHaveBeenCalled();
})); }));
it("are registered when _converse.js reconnected", mock.initConverse(function (_converse) { it("are registered when _converse.js reconnected", mock.initConverse(function (_converse) {
spyOn(_converse, 'registerPingHandler').andCallThrough(); spyOn(_converse, 'registerPingHandler').and.callThrough();
spyOn(_converse, 'registerPongHandler').andCallThrough(); spyOn(_converse, 'registerPongHandler').and.callThrough();
_converse.emit('reconnected'); _converse.emit('reconnected');
expect(_converse.registerPingHandler).toHaveBeenCalled(); expect(_converse.registerPingHandler).toHaveBeenCalled();
expect(_converse.registerPongHandler).toHaveBeenCalled(); expect(_converse.registerPongHandler).toHaveBeenCalled();
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
it("is sent out when _converse.js pings a server", mock.initConverse(function (_converse) { it("is sent out when _converse.js pings a server", mock.initConverse(function (_converse) {
var sent_stanza, IQ_id; var sent_stanza, IQ_id;
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq; sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"jquery", "jquery",
"converse-core", "converse-core",
"mock", "mock",
"test_utils", "test-utils",
"lodash"], factory); "lodash"], factory);
} (this, function ($, converse, mock, test_utils, _) { } (this, function ($, converse, mock, test_utils, _) {
"use strict"; "use strict";
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"jquery", "jquery",
"converse-core", "converse-core",
"mock", "mock",
"test_utils"], factory); "test-utils"], factory);
} (this, function ($, converse, mock, test_utils) { } (this, function ($, converse, mock, test_utils) {
"use strict"; "use strict";
var Strophe = converse.env.Strophe; var Strophe = converse.env.Strophe;
...@@ -46,175 +46,171 @@ ...@@ -46,175 +46,171 @@
* that session. A client MUST acknowledge each roster push with an IQ * that session. A client MUST acknowledge each roster push with an IQ
* stanza of type "result". * stanza of type "result".
*/ */
it("Subscribe to contact, contact accepts and subscribes back", mock.initConverse(function (_converse) { it("Subscribe to contact, contact accepts and subscribes back", mock.initConverseWithAsync(function (done, _converse) {
/* The process by which a user subscribes to a contact, including /* The process by which a user subscribes to a contact, including
* the interaction between roster items and subscription states. * the interaction between roster items and subscription states.
*/ */
_converse.roster_groups = false; _converse.roster_groups = false;
var contact, stanza, sent_stanza, IQ_id; var contact, stanza, sent_stanza, IQ_id;
runs(function () { test_utils.openControlBox(_converse);
test_utils.openControlBox(_converse); var panel = _converse.chatboxviews.get('controlbox').contactspanel;
spyOn(panel, "addContactFromForm").and.callThrough();
spyOn(_converse.roster, "addAndSubscribe").and.callThrough();
spyOn(_converse.roster, "addContact").and.callThrough();
spyOn(_converse.roster, "sendContactAddIQ").and.callThrough();
spyOn(_converse, "getVCard").and.callThrough();
var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
waits(100); panel.delegateEvents(); // Rebind all events so that our spy gets called
runs(function () {
var panel = _converse.chatboxviews.get('controlbox').contactspanel;
spyOn(panel, "addContactFromForm").andCallThrough();
spyOn(_converse.roster, "addAndSubscribe").andCallThrough();
spyOn(_converse.roster, "addContact").andCallThrough();
spyOn(_converse.roster, "sendContactAddIQ").andCallThrough();
spyOn(_converse, "getVCard").andCallThrough();
var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) {
sent_stanza = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
});
panel.delegateEvents(); // Rebind all events so that our spy gets called
/* Add a new contact through the UI */ /* Add a new contact through the UI */
var $form = panel.$('form.add-xmpp-contact'); var $form = panel.$('form.add-xmpp-contact');
expect($form.is(":visible")).toBeFalsy(); expect($form.is(":visible")).toBeFalsy();
// Click the "Add a contact" link. // Click the "Add a contact" link.
panel.$('.toggle-xmpp-contact-form').click(); panel.$('.toggle-xmpp-contact-form').click();
// Check that the $form appears // Check that the $form appears
expect($form.is(":visible")).toBeTruthy(); expect($form.is(":visible")).toBeTruthy();
// Fill in the form and submit // Fill in the form and submit
$form.find('input').val('contact@example.org'); $form.find('input').val('contact@example.org');
$form.submit(); $form.submit();
/* In preparation for being able to render the contact in the /* In preparation for being able to render the contact in the
* user's client interface and for the server to keep track of the * user's client interface and for the server to keep track of the
* subscription, the user's client SHOULD perform a "roster set" * subscription, the user's client SHOULD perform a "roster set"
* for the new roster item. * for the new roster item.
*/ */
expect(panel.addContactFromForm).toHaveBeenCalled(); expect(panel.addContactFromForm).toHaveBeenCalled();
expect(_converse.roster.addAndSubscribe).toHaveBeenCalled(); expect(_converse.roster.addAndSubscribe).toHaveBeenCalled();
expect(_converse.roster.addContact).toHaveBeenCalled(); expect(_converse.roster.addContact).toHaveBeenCalled();
// The form should not be visible anymore. // The form should not be visible anymore.
expect($form.is(":visible")).toBeFalsy(); expect($form.is(":visible")).toBeFalsy();
/* _converse request consists of sending an IQ /* _converse request consists of sending an IQ
* stanza of type='set' containing a <query/> element qualified by * stanza of type='set' containing a <query/> element qualified by
* the 'jabber:iq:roster' namespace, which in turn contains an * the 'jabber:iq:roster' namespace, which in turn contains an
* <item/> element that defines the new roster item; the <item/> * <item/> element that defines the new roster item; the <item/>
* element MUST possess a 'jid' attribute, MAY possess a 'name' * element MUST possess a 'jid' attribute, MAY possess a 'name'
* attribute, MUST NOT possess a 'subscription' attribute, and MAY * attribute, MUST NOT possess a 'subscription' attribute, and MAY
* contain one or more <group/> child elements: * contain one or more <group/> child elements:
* *
* <iq type='set' id='set1'> * <iq type='set' id='set1'>
* <query xmlns='jabber:iq:roster'> * <query xmlns='jabber:iq:roster'>
* <item * <item
* jid='contact@example.org' * jid='contact@example.org'
* name='MyContact'> * name='MyContact'>
* <group>MyBuddies</group> * <group>MyBuddies</group>
* </item> * </item>
* </query> * </query>
* </iq> * </iq>
*/ */
expect(_converse.roster.sendContactAddIQ).toHaveBeenCalled(); expect(_converse.roster.sendContactAddIQ).toHaveBeenCalled();
expect(sent_stanza.toLocaleString()).toBe( expect(sent_stanza.toLocaleString()).toBe(
"<iq type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+ "<iq type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
"<query xmlns='jabber:iq:roster'>"+ "<query xmlns='jabber:iq:roster'>"+
"<item jid='contact@example.org' name='contact@example.org'/>"+ "<item jid='contact@example.org' name='contact@example.org'/>"+
"</query>"+ "</query>"+
"</iq>" "</iq>"
); );
/* As a result, the user's server (1) MUST initiate a roster push /* As a result, the user's server (1) MUST initiate a roster push
* for the new roster item to all available resources associated * for the new roster item to all available resources associated
* with _converse user that have requested the roster, setting the * with _converse user that have requested the roster, setting the
* 'subscription' attribute to a value of "none"; and (2) MUST * 'subscription' attribute to a value of "none"; and (2) MUST
* reply to the sending resource with an IQ result indicating the * reply to the sending resource with an IQ result indicating the
* success of the roster set: * success of the roster set:
* *
* <iq type='set'> * <iq type='set'>
* <query xmlns='jabber:iq:roster'> * <query xmlns='jabber:iq:roster'>
* <item * <item
* jid='contact@example.org' * jid='contact@example.org'
* subscription='none' * subscription='none'
* name='MyContact'> * name='MyContact'>
* <group>MyBuddies</group> * <group>MyBuddies</group>
* </item> * </item>
* </query> * </query>
* </iq> * </iq>
*/ */
var create = _converse.roster.create; var create = _converse.roster.create;
spyOn(_converse.connection, 'send').andCallFake(function (stanza) { spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
sent_stanza = stanza; sent_stanza = stanza;
}); });
spyOn(_converse.roster, 'create').andCallFake(function () { spyOn(_converse.roster, 'create').and.callFake(function () {
contact = create.apply(_converse.roster, arguments); contact = create.apply(_converse.roster, arguments);
spyOn(contact, 'subscribe').andCallThrough(); spyOn(contact, 'subscribe').and.callThrough();
return contact; return contact;
}); });
stanza = $iq({'type': 'set'}).c('query', {'xmlns': 'jabber:iq:roster'}) stanza = $iq({'type': 'set'}).c('query', {'xmlns': 'jabber:iq:roster'})
.c('item', { .c('item', {
'jid': 'contact@example.org', 'jid': 'contact@example.org',
'subscription': 'none', 'subscription': 'none',
'name': 'contact@example.org'}); 'name': 'contact@example.org'});
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
/* /*
* <iq type='result' id='set1'/> * <iq type='result' id='set1'/>
*/ */
stanza = $iq({'type': 'result', 'id':IQ_id}); stanza = $iq({'type': 'result', 'id':IQ_id});
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
// A contact should now have been created // A contact should now have been created
expect(_converse.roster.get('contact@example.org') instanceof _converse.RosterContact).toBeTruthy(); expect(_converse.roster.get('contact@example.org') instanceof _converse.RosterContact).toBeTruthy();
expect(contact.get('jid')).toBe('contact@example.org'); expect(contact.get('jid')).toBe('contact@example.org');
expect(_converse.getVCard).toHaveBeenCalled(); expect(_converse.getVCard).toHaveBeenCalled();
/* To subscribe to the contact's presence information, /* To subscribe to the contact's presence information,
* the user's client MUST send a presence stanza of * the user's client MUST send a presence stanza of
* type='subscribe' to the contact: * type='subscribe' to the contact:
* *
* <presence to='contact@example.org' type='subscribe'/> * <presence to='contact@example.org' type='subscribe'/>
*/ */
expect(contact.subscribe).toHaveBeenCalled(); expect(contact.subscribe).toHaveBeenCalled();
expect(sent_stanza.toLocaleString()).toBe( // Strophe adds the xmlns attr (although not in spec) expect(sent_stanza.toLocaleString()).toBe( // Strophe adds the xmlns attr (although not in spec)
"<presence to='contact@example.org' type='subscribe' xmlns='jabber:client'>"+ "<presence to='contact@example.org' type='subscribe' xmlns='jabber:client'>"+
"<nick xmlns='http://jabber.org/protocol/nick'>Max Mustermann</nick>"+ "<nick xmlns='http://jabber.org/protocol/nick'>Max Mustermann</nick>"+
"</presence>" "</presence>"
); );
/* As a result, the user's server MUST initiate a second roster /* As a result, the user's server MUST initiate a second roster
* push to all of the user's available resources that have * push to all of the user's available resources that have
* requested the roster, setting the contact to the pending * requested the roster, setting the contact to the pending
* sub-state of the 'none' subscription state; _converse pending * sub-state of the 'none' subscription state; _converse pending
* sub-state is denoted by the inclusion of the ask='subscribe' * sub-state is denoted by the inclusion of the ask='subscribe'
* attribute in the roster item: * attribute in the roster item:
* *
* <iq type='set'> * <iq type='set'>
* <query xmlns='jabber:iq:roster'> * <query xmlns='jabber:iq:roster'>
* <item * <item
* jid='contact@example.org' * jid='contact@example.org'
* subscription='none' * subscription='none'
* ask='subscribe' * ask='subscribe'
* name='MyContact'> * name='MyContact'>
* <group>MyBuddies</group> * <group>MyBuddies</group>
* </item> * </item>
* </query> * </query>
* </iq> * </iq>
*/ */
spyOn(_converse.roster, "updateContact").andCallThrough(); spyOn(_converse.roster, "updateContact").and.callThrough();
stanza = $iq({'type': 'set', 'from': 'dummy@localhost'}) stanza = $iq({'type': 'set', 'from': 'dummy@localhost'})
.c('query', {'xmlns': 'jabber:iq:roster'}) .c('query', {'xmlns': 'jabber:iq:roster'})
.c('item', { .c('item', {
'jid': 'contact@example.org', 'jid': 'contact@example.org',
'subscription': 'none', 'subscription': 'none',
'ask': 'subscribe', 'ask': 'subscribe',
'name': 'contact@example.org'}); 'name': 'contact@example.org'});
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(_converse.roster.updateContact).toHaveBeenCalled(); expect(_converse.roster.updateContact).toHaveBeenCalled();
}); // Check that the user is now properly shown as a pending
waits(50); // contact in the roster.
runs(function () { test_utils.waitUntil(function () {
// Check that the user is now properly shown as a pending return $('a:contains("Pending contacts")').length;
// contact in the roster. }).then(function () {
var $header = $('a:contains("Pending contacts")'); var $header = $('a:contains("Pending contacts")');
expect($header.length).toBe(1); expect($header.length).toBe(1);
expect($header.is(":visible")).toBeTruthy(); expect($header.is(":visible")).toBeTruthy();
var $contacts = $header.parent().nextUntil('dt', 'dd'); var $contacts = $header.parent().nextUntil('dt', 'dd');
expect($contacts.length).toBe(1); expect($contacts.length).toBe(1);
spyOn(contact, "ackSubscribe").andCallThrough(); spyOn(contact, "ackSubscribe").and.callThrough();
/* Here we assume the "happy path" that the contact /* Here we assume the "happy path" that the contact
* approves the subscription request * approves the subscription request
* *
...@@ -301,8 +297,8 @@ ...@@ -301,8 +297,8 @@
* *
* <presence from='contact@example.org' to='user@example.com' type='subscribe'/> * <presence from='contact@example.org' to='user@example.com' type='subscribe'/>
*/ */
spyOn(contact, 'authorize').andCallThrough(); spyOn(contact, 'authorize').and.callThrough();
spyOn(_converse.roster, 'handleIncomingSubscription').andCallThrough(); spyOn(_converse.roster, 'handleIncomingSubscription').and.callThrough();
stanza = $pres({ stanza = $pres({
'to': _converse.bare_jid, 'to': _converse.bare_jid,
'from': 'contact@example.org/resource', 'from': 'contact@example.org/resource',
...@@ -348,6 +344,7 @@ ...@@ -348,6 +344,7 @@
// The class on the contact will now have switched. // The class on the contact will now have switched.
expect($contacts.hasClass('to')).toBeFalsy(); expect($contacts.hasClass('to')).toBeFalsy();
expect($contacts.hasClass('both')).toBeTruthy(); expect($contacts.hasClass('both')).toBeTruthy();
done();
}); });
})); }));
...@@ -356,110 +353,101 @@ ...@@ -356,110 +353,101 @@
* the interaction between roster items and subscription states. * the interaction between roster items and subscription states.
*/ */
var contact, stanza, sent_stanza, sent_IQ; var contact, stanza, sent_stanza, sent_IQ;
runs(function () { test_utils.openControlBox(_converse);
test_utils.openControlBox(_converse); // Add a new roster contact via roster push
stanza = $iq({'type': 'set'}).c('query', {'xmlns': 'jabber:iq:roster'})
.c('item', {
'jid': 'contact@example.org',
'subscription': 'none',
'ask': 'subscribe',
'name': 'contact@example.org'});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
// A pending contact should now exist.
contact = _converse.roster.get('contact@example.org');
expect(_converse.roster.get('contact@example.org') instanceof _converse.RosterContact).toBeTruthy();
spyOn(contact, "ackUnsubscribe").and.callThrough();
spyOn(_converse.connection, 'send').and.callFake(function (stanza) {
sent_stanza = stanza;
}); });
waits(100); spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
runs(function () { sent_IQ = iq;
// Add a new roster contact via roster push
stanza = $iq({'type': 'set'}).c('query', {'xmlns': 'jabber:iq:roster'})
.c('item', {
'jid': 'contact@example.org',
'subscription': 'none',
'ask': 'subscribe',
'name': 'contact@example.org'});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
}); });
waits(50); /* We now assume the contact declines the subscription
runs(function () { * requests.
// A pending contact should now exist. *
contact = _converse.roster.get('contact@example.org'); /* Upon receiving the presence stanza of type "unsubscribed"
expect(_converse.roster.get('contact@example.org') instanceof _converse.RosterContact).toBeTruthy(); * addressed to the user, the user's server (1) MUST deliver
spyOn(contact, "ackUnsubscribe").andCallThrough(); * that presence stanza to the user and (2) MUST initiate a
* roster push to all of the user's available resources that
spyOn(_converse.connection, 'send').andCallFake(function (stanza) { * have requested the roster, containing an updated roster
sent_stanza = stanza; * item for the contact with the 'subscription' attribute
}); * set to a value of "none" and with no 'ask' attribute:
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { *
sent_IQ = iq; * <presence
}); * from='contact@example.org'
/* We now assume the contact declines the subscription * to='user@example.com'
* requests. * type='unsubscribed'/>
* *
/* Upon receiving the presence stanza of type "unsubscribed" * <iq type='set'>
* addressed to the user, the user's server (1) MUST deliver * <query xmlns='jabber:iq:roster'>
* that presence stanza to the user and (2) MUST initiate a * <item
* roster push to all of the user's available resources that * jid='contact@example.org'
* have requested the roster, containing an updated roster * subscription='none'
* item for the contact with the 'subscription' attribute * name='MyContact'>
* set to a value of "none" and with no 'ask' attribute: * <group>MyBuddies</group>
* * </item>
* <presence * </query>
* from='contact@example.org' * </iq>
* to='user@example.com' */
* type='unsubscribed'/> // FIXME: also add the <iq>
* stanza = $pres({
* <iq type='set'> 'to': _converse.bare_jid,
* <query xmlns='jabber:iq:roster'> 'from': 'contact@example.org',
* <item 'type': 'unsubscribed'
* jid='contact@example.org' });
* subscription='none' _converse.connection._dataRecv(test_utils.createRequest(stanza));
* name='MyContact'>
* <group>MyBuddies</group>
* </item>
* </query>
* </iq>
*/
// FIXME: also add the <iq>
stanza = $pres({
'to': _converse.bare_jid,
'from': 'contact@example.org',
'type': 'unsubscribed'
});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
/* Upon receiving the presence stanza of type "unsubscribed", /* Upon receiving the presence stanza of type "unsubscribed",
* the user SHOULD acknowledge receipt of that subscription * the user SHOULD acknowledge receipt of that subscription
* state notification through either "affirming" it by * state notification through either "affirming" it by
* sending a presence stanza of type "unsubscribe * sending a presence stanza of type "unsubscribe
*/ */
expect(contact.ackUnsubscribe).toHaveBeenCalled(); expect(contact.ackUnsubscribe).toHaveBeenCalled();
expect(sent_stanza.toLocaleString()).toBe( expect(sent_stanza.toLocaleString()).toBe(
"<presence type='unsubscribe' to='contact@example.org' xmlns='jabber:client'/>" "<presence type='unsubscribe' to='contact@example.org' xmlns='jabber:client'/>"
); );
/* _converse.js will then also automatically remove the /* _converse.js will then also automatically remove the
* contact from the user's roster. * contact from the user's roster.
*/ */
expect(sent_IQ.toLocaleString()).toBe( expect(sent_IQ.toLocaleString()).toBe(
"<iq type='set' xmlns='jabber:client'>"+ "<iq type='set' xmlns='jabber:client'>"+
"<query xmlns='jabber:iq:roster'>"+ "<query xmlns='jabber:iq:roster'>"+
"<item jid='contact@example.org' subscription='remove'/>"+ "<item jid='contact@example.org' subscription='remove'/>"+
"</query>"+ "</query>"+
"</iq>" "</iq>"
); );
});
})); }));
it("Unsubscribe to a contact when subscription is mutual", mock.initConverse(function (_converse) { it("Unsubscribe to a contact when subscription is mutual", mock.initConverseWithAsync(function (done, _converse) {
var sent_IQ, IQ_id, jid = 'annegreet.gomez@localhost'; var sent_IQ, IQ_id, jid = 'annegreet.gomez@localhost';
_converse.roster_groups = false; _converse.roster_groups = false;
runs(function () { test_utils.openControlBox(_converse);
test_utils.openControlBox(_converse); test_utils.createContacts(_converse, 'current');
test_utils.createContacts(_converse, 'current'); spyOn(window, 'confirm').and.returnValue(true);
}); // We now have a contact we want to remove
waits(50); expect(_converse.roster.get(jid) instanceof _converse.RosterContact).toBeTruthy();
runs(function () {
spyOn(window, 'confirm').andReturn(true);
// We now have a contact we want to remove
expect(_converse.roster.get(jid) instanceof _converse.RosterContact).toBeTruthy();
var sendIQ = _converse.connection.sendIQ; var sendIQ = _converse.connection.sendIQ;
spyOn(_converse.connection, 'sendIQ').andCallFake(function (iq, callback, errback) { spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
sent_IQ = iq; sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback); IQ_id = sendIQ.bind(this)(iq, callback, errback);
}); });
test_utils.waitUntil(function () {
return $('a:contains("My contacts")').length;
}).then(function () {
var $header = $('a:contains("My contacts")'); var $header = $('a:contains("My contacts")');
// remove the first user // remove the first user
$($header.parent().nextUntil('dt', 'dd').find('.remove-xmpp-contact').get(0)).click(); $($header.parent().nextUntil('dt', 'dd').find('.remove-xmpp-contact').get(0)).click();
...@@ -497,31 +485,31 @@ ...@@ -497,31 +485,31 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
// Our contact has now been removed // Our contact has now been removed
expect(typeof _converse.roster.get(jid) === "undefined").toBeTruthy(); expect(typeof _converse.roster.get(jid) === "undefined").toBeTruthy();
done();
}); });
})); }));
it("Receiving a subscription request", mock.initConverse(function (_converse) { it("Receiving a subscription request", mock.initConverse(function (_converse) {
runs(function () { test_utils.openControlBox(_converse);
test_utils.openControlBox(_converse); test_utils.createContacts(_converse, 'current'); // Create some contacts so that we can test positioning
test_utils.createContacts(_converse, 'current'); // Create some contacts so that we can test positioning spyOn(_converse, "emit");
}); /* <presence
waits(50); * from='user@example.com'
runs(function () { * to='contact@example.org'
spyOn(_converse, "emit"); * type='subscribe'/>
/* <presence */
* from='user@example.com' var stanza = $pres({
* to='contact@example.org' 'to': _converse.bare_jid,
* type='subscribe'/> 'from': 'contact@example.org',
*/ 'type': 'subscribe'
var stanza = $pres({ }).c('nick', {
'to': _converse.bare_jid, 'xmlns': Strophe.NS.NICK,
'from': 'contact@example.org', }).t('Clint Contact');
'type': 'subscribe' _converse.connection._dataRecv(test_utils.createRequest(stanza));
}).c('nick', { expect(_converse.emit).toHaveBeenCalledWith('contactRequest', jasmine.any(Object));
'xmlns': Strophe.NS.NICK, test_utils.waitUntil(function () {
}).t('Clint Contact'); return $('a:contains("Contact requests")').length;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); }).then(function () {
expect(_converse.emit).toHaveBeenCalledWith('contactRequest', jasmine.any(Object));
var $header = $('a:contains("Contact requests")'); var $header = $('a:contains("Contact requests")');
expect($header.length).toBe(1); expect($header.length).toBe(1);
expect($header.is(":visible")).toBeTruthy(); expect($header.is(":visible")).toBeTruthy();
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils"], factory); define(["mock", "converse-core", "test-utils"], factory);
} (this, function (mock, converse, test_utils) { } (this, function (mock, converse, test_utils) {
var $ = converse.env.jQuery; var $ = converse.env.jQuery;
var Strophe = converse.env.Strophe; var Strophe = converse.env.Strophe;
...@@ -8,44 +8,40 @@ ...@@ -8,44 +8,40 @@
describe("The Registration Panel", function () { describe("The Registration Panel", function () {
it("is not available unless allow_registration=true", mock.initConverse(function (_converse) { it("is not available unless allow_registration=true", mock.initConverse(function (_converse) {
runs(test_utils.openControlBox); test_utils.openControlBox();
waits(50); var cbview = _converse.chatboxviews.get('controlbox');
runs(function () { expect(cbview.$('#controlbox-tabs li').length).toBe(1);
var cbview = _converse.chatboxviews.get('controlbox'); expect(cbview.$('#controlbox-tabs li').text().trim()).toBe("Sign in");
expect(cbview.$('#controlbox-tabs li').length).toBe(1);
expect(cbview.$('#controlbox-tabs li').text().trim()).toBe("Sign in"); }, { auto_login: false,
}); allow_registration: false,
}, { auto_login: false, }));
allow_registration: false,
}));
it("can be opened by clicking on the registration tab", mock.initConverse(function (_converse) { it("can be opened by clicking on the registration tab", mock.initConverse(function (_converse) {
var cbview = _converse.chatboxviews.get('controlbox'); var cbview = _converse.chatboxviews.get('controlbox');
runs(test_utils.openControlBox); test_utils.openControlBox();
waits(50); var $tabs = cbview.$('#controlbox-tabs');
runs(function () { var $panels = cbview.$('.controlbox-panes');
var $tabs = cbview.$('#controlbox-tabs'); var $login = $panels.children().first();
var $panels = cbview.$('.controlbox-panes'); var $registration = $panels.children().last();
var $login = $panels.children().first(); expect($tabs.find('li').first().text()).toBe('Sign in');
var $registration = $panels.children().last(); expect($tabs.find('li').last().text()).toBe('Register');
expect($tabs.find('li').first().text()).toBe('Sign in');
expect($tabs.find('li').last().text()).toBe('Register'); spyOn(cbview, 'switchTab').and.callThrough();
cbview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
spyOn(cbview, 'switchTab').andCallThrough(); $tabs.find('li').last().find('a').click(); // Click the Register tab
cbview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called expect($login.is(':visible')).toBe(false);
$tabs.find('li').last().find('a').click(); // Click the Register tab expect($registration.is(':visible')).toBe(true);
expect($login.is(':visible')).toBe(false); expect(cbview.switchTab).toHaveBeenCalled();
expect($registration.is(':visible')).toBe(true);
expect(cbview.switchTab).toHaveBeenCalled(); }, { auto_login: false,
}); allow_registration: true,
}, { auto_login: false, }));
allow_registration: true,
}));
it("allows the user to choose an XMPP provider's domain", mock.initConverse(function (_converse) { it("allows the user to choose an XMPP provider's domain", mock.initConverse(function (_converse) {
var cbview = _converse.chatboxviews.get('controlbox'); var cbview = _converse.chatboxviews.get('controlbox');
var registerview = cbview.registerpanel; var registerview = cbview.registerpanel;
spyOn(registerview, 'onProviderChosen').andCallThrough(); spyOn(registerview, 'onProviderChosen').and.callThrough();
registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
spyOn(_converse.connection, 'connect'); spyOn(_converse.connection, 'connect');
var $tabs = cbview.$('#controlbox-tabs'); var $tabs = cbview.$('#controlbox-tabs');
...@@ -72,12 +68,12 @@ ...@@ -72,12 +68,12 @@
var cbview = _converse.chatboxviews.get('controlbox'); var cbview = _converse.chatboxviews.get('controlbox');
cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
var registerview = _converse.chatboxviews.get('controlbox').registerpanel; var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
spyOn(registerview, 'onProviderChosen').andCallThrough(); spyOn(registerview, 'onProviderChosen').and.callThrough();
spyOn(registerview, 'getRegistrationFields').andCallThrough(); spyOn(registerview, 'getRegistrationFields').and.callThrough();
spyOn(registerview, 'onRegistrationFields').andCallThrough(); spyOn(registerview, 'onRegistrationFields').and.callThrough();
spyOn(registerview, 'renderRegistrationForm').andCallThrough(); spyOn(registerview, 'renderRegistrationForm').and.callThrough();
registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
spyOn(_converse.connection, 'connect').andCallThrough(); spyOn(_converse.connection, 'connect').and.callThrough();
expect(registerview._registering).toBeFalsy(); expect(registerview._registering).toBeFalsy();
expect(_converse.connection.connected).toBeFalsy(); expect(_converse.connection.connected).toBeFalsy();
...@@ -120,12 +116,12 @@ ...@@ -120,12 +116,12 @@
var cbview = _converse.chatboxviews.get('controlbox'); var cbview = _converse.chatboxviews.get('controlbox');
cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
var registerview = _converse.chatboxviews.get('controlbox').registerpanel; var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
spyOn(registerview, 'onProviderChosen').andCallThrough(); spyOn(registerview, 'onProviderChosen').and.callThrough();
spyOn(registerview, 'getRegistrationFields').andCallThrough(); spyOn(registerview, 'getRegistrationFields').and.callThrough();
spyOn(registerview, 'onRegistrationFields').andCallThrough(); spyOn(registerview, 'onRegistrationFields').and.callThrough();
spyOn(registerview, 'renderRegistrationForm').andCallThrough(); spyOn(registerview, 'renderRegistrationForm').and.callThrough();
registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
spyOn(_converse.connection, 'connect').andCallThrough(); spyOn(_converse.connection, 'connect').and.callThrough();
registerview.$('input[name=domain]').val('conversejs.org'); registerview.$('input[name=domain]').val('conversejs.org');
registerview.$('input[type=submit]').click(); registerview.$('input[type=submit]').click();
...@@ -158,7 +154,7 @@ ...@@ -158,7 +154,7 @@
registerview.$('input[type=submit]').click(); registerview.$('input[type=submit]').click();
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.children('query').children().length).toBe(3); expect($stanza.children('query').children().length).toBe(3);
expect($stanza.children('query').children()[0].tagName).toBe('username'); expect($stanza.children('query').children()[0].tagName).toBe('username');
}, { auto_login: false, }, { auto_login: false,
...@@ -169,12 +165,12 @@ ...@@ -169,12 +165,12 @@
var cbview = _converse.chatboxviews.get('controlbox'); var cbview = _converse.chatboxviews.get('controlbox');
cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
var registerview = _converse.chatboxviews.get('controlbox').registerpanel; var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
spyOn(registerview, 'onProviderChosen').andCallThrough(); spyOn(registerview, 'onProviderChosen').and.callThrough();
spyOn(registerview, 'getRegistrationFields').andCallThrough(); spyOn(registerview, 'getRegistrationFields').and.callThrough();
spyOn(registerview, 'onRegistrationFields').andCallThrough(); spyOn(registerview, 'onRegistrationFields').and.callThrough();
spyOn(registerview, 'renderRegistrationForm').andCallThrough(); spyOn(registerview, 'renderRegistrationForm').and.callThrough();
registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called registerview.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
spyOn(_converse.connection, 'connect').andCallThrough(); spyOn(_converse.connection, 'connect').and.callThrough();
registerview.$('input[name=domain]').val('conversejs.org'); registerview.$('input[name=domain]').val('conversejs.org');
registerview.$('input[type=submit]').click(); registerview.$('input[type=submit]').click();
...@@ -209,7 +205,7 @@ ...@@ -209,7 +205,7 @@
registerview.$('input[type=submit]').click(); registerview.$('input[type=submit]').click();
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.children('query').children().length).toBe(1); expect($stanza.children('query').children().length).toBe(1);
expect($stanza.children('query').children().children().length).toBe(3); expect($stanza.children('query').children().children().length).toBe(3);
expect($stanza.children('query').children().children()[0].tagName).toBe('field'); expect($stanza.children('query').children().children()[0].tagName).toBe('field');
......
(function (root, factory) { (function (root, factory) {
define(["converse-core"], factory); define(["jasmine-html", "converse-core"], factory);
} (this, function (converse) { } (this, function (jasmine, converse) {
var utils = converse.env.utils, var utils = converse.env.utils,
_ = converse.env._; _ = converse.env._;
......
(function (root, factory) { (function (root, factory) {
define(["mock", "converse-core", "test_utils"], factory); define(["mock", "converse-core", "test-utils"], factory);
} (this, function (mock, converse, test_utils) { } (this, function (mock, converse, test_utils) {
var $ = converse.env.jQuery; var $ = converse.env.jQuery;
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
it("won't send <show>online</show> when setting a custom status message", mock.initConverse(function (_converse) { it("won't send <show>online</show> when setting a custom status message", mock.initConverse(function (_converse) {
_converse.xmppstatus.save({'status': 'online'}); _converse.xmppstatus.save({'status': 'online'});
spyOn(_converse.xmppstatus, 'setStatusMessage').andCallThrough(); spyOn(_converse.xmppstatus, 'setStatusMessage').and.callThrough();
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
_converse.xmppstatus.setStatusMessage("I'm also happy!"); _converse.xmppstatus.setStatusMessage("I'm also happy!");
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
var $stanza = $(_converse.connection.send.argsForCall[0][0].tree()); var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
expect($stanza.children().length).toBe(2); expect($stanza.children().length).toBe(2);
expect($stanza.children('status').length).toBe(1); expect($stanza.children('status').length).toBe(1);
expect($stanza.children('status').text()).toBe("I'm also happy!"); expect($stanza.children('status').text()).toBe("I'm also happy!");
......
...@@ -21,6 +21,7 @@ require.config({ ...@@ -21,6 +21,7 @@ require.config({
"backbone.browserStorage": "node_modules/backbone.browserStorage/backbone.browserStorage", "backbone.browserStorage": "node_modules/backbone.browserStorage/backbone.browserStorage",
"backbone.overview": "node_modules/backbone.overview/backbone.overview", "backbone.overview": "node_modules/backbone.overview/backbone.overview",
"eventemitter": "node_modules/otr/build/dep/eventemitter", "eventemitter": "node_modules/otr/build/dep/eventemitter",
"es6-promise": "node_modules/es6-promise/dist/es6-promise",
"jquery": "node_modules/jquery/dist/jquery", "jquery": "node_modules/jquery/dist/jquery",
"jquery-private": "src/jquery-private", "jquery-private": "src/jquery-private",
"jquery.browser": "node_modules/jquery.browser/dist/jquery.browser", "jquery.browser": "node_modules/jquery.browser/dist/jquery.browser",
......
...@@ -4,12 +4,16 @@ ...@@ -4,12 +4,16 @@
<head> <head>
<title>Converse.js Tests</title> <title>Converse.js Tests</title>
<meta name="description" content="Converse.js: A chat client for your website" /> <meta name="description" content="Converse.js: A chat client for your website" />
<link rel="shortcut icon" type="image/png" href="components/jasmine/images/jasmine_favicon.png"> <link rel="shortcut icon" type="image/png" href="node_modules/jasmine-core/images/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" media="screen" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
<link rel="stylesheet" type="text/css" media="screen" href="css/jasmine.css"> <link rel="stylesheet" type="text/css" media="screen" href="css/jasmine.css">
<link type="text/css" rel="stylesheet" media="screen" href="css/theme.css" /> <link type="text/css" rel="stylesheet" media="screen" href="css/theme.css" />
<link type="text/css" rel="stylesheet" media="screen" href="css/converse.css" /> <link type="text/css" rel="stylesheet" media="screen" href="css/converse.css" />
<script src="src/config.js"></script> <script src="src/config.js"></script>
<script data-main="tests/main" src="node_modules/requirejs/require.js"></script> <script data-main="tests/runner" src="node_modules/requirejs/require.js"></script>
<style> <style>
.tests-brand-heading { .tests-brand-heading {
margin-top: 1em; margin-top: 1em;
...@@ -21,7 +25,8 @@ ...@@ -21,7 +25,8 @@
<body> <body>
<div id="header_wrap" class="outer"> <div id="header_wrap" class="outer">
<header class="inner"> <header class="inner">
<h1 class="brand-heading tests-brand-heading"><i class="icon-conversejs"></i> Converse.js</h1> <h1 class="brand-heading tests-brand-heading">
<i class="icon-conversejs"></i> Converse.js</h1>
<h2 id="project_tagline">Tests</h2> <h2 id="project_tagline">Tests</h2>
</header> </header>
</div> </div>
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
'preventDefault': function () {} 'preventDefault': function () {}
}; };
mock.mock_connection = function () { mock.mock_connection = function () { // eslint-disable-line wrap-iife
return function () { return function () {
Strophe.Bosh.prototype._processRequest = function () {}; // Don't attempt to send out stanzas Strophe.Bosh.prototype._processRequest = function () {}; // Don't attempt to send out stanzas
var c = new Strophe.Connection('jasmine tests'); var c = new Strophe.Connection('jasmine tests');
...@@ -76,25 +76,33 @@ ...@@ -76,25 +76,33 @@
}; };
}(); }();
function initConverse (settings) {
window.localStorage.clear();
window.sessionStorage.clear();
var converse = converse_api.initialize(_.extend({
i18n: window.locales.en,
auto_subscribe: false,
bosh_service_url: 'localhost',
connection: mock.mock_connection(),
animate: false,
no_trimming: true,
auto_login: true,
jid: 'dummy@localhost',
password: 'secret',
debug: false
}, settings || {}));
converse.ChatBoxViews.prototype.trimChat = function () {};
return converse;
}
mock.initConverseWithAsync = function (func, settings) {
return function (done) {
return func(done, initConverse(settings));
};
};
mock.initConverse = function (func, settings) { mock.initConverse = function (func, settings) {
return function () { return function () {
window.localStorage.clear(); initConverse(settings);
window.sessionStorage.clear(); return func(initConverse(settings));
var converse = converse_api.initialize(_.extend({
i18n: window.locales.en,
auto_subscribe: false,
bosh_service_url: 'localhost',
connection: mock.mock_connection(),
animate: false,
no_trimming: true,
auto_login: true,
jid: 'dummy@localhost',
password: 'secret',
debug: false
}, settings || {}));
converse.ChatBoxViews.prototype.trimChat = function () {};
return func(converse);
}; };
}; };
return mock; return mock;
......
/*global document, require, setInterval, clearInterval, eval, phantom, console */
var system = require('system');
function waitFor(testFx, onReady, timeOutMillis) {
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
"use strict";
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 40001, //< Default Max Timeout is 10s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); // eslint-disable-line no-eval
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
// Do what it's supposed to do once the condition is fulfilled
typeof(onReady) === "string" ? eval(onReady) : onReady(); // eslint-disable-line no-eval
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 100ms
}
if (system.args.length !== 2) {
console.log('Usage: run-jasmine2.js URL');
phantom.exit(1);
}
var page = require('webpage').create();
page.onConsoleMessage = function(msg) {
// Route "console.log()" calls from within the Page context to the main
// Phantom context (i.e. current "this")
console.log(msg);
};
page.open(system.args[1], function(status){
"use strict";
if (status !== "success") {
console.log("Unable to access network");
phantom.exit();
} else {
waitFor(function(){
return page.evaluate(function(){
return (document.body.querySelector('.jasmine-symbol-summary .pending') === null &&
document.body.querySelector('.jasmine-duration') !== null);
});
}, function(){
var exitCode = page.evaluate(function(){
console.log('');
var title = 'Jasmine';
var version = document.body.querySelector('.jasmine-version').innerText;
var duration = document.body.querySelector('.jasmine-duration').innerText;
var banner = title + ' ' + version + ' ' + duration;
console.log(banner);
var list = document.body.querySelectorAll('.jasmine-results > .jasmine-failures > .jasmine-spec-detail.jasmine-failed');
if (list && list.length > 0) {
console.log('');
console.log(list.length + ' test(s) FAILED:');
for (var i = 0; i < list.length; ++i) {
var el = list[i],
desc = el.querySelector('.jasmine-description'),
msg = el.querySelector('.jasmine-messages > .jasmine-result-message');
console.log('');
console.log(desc.innerText);
console.log(msg.innerText);
console.log('');
}
return 1;
} else {
console.log(document.body.querySelector('.jasmine-alert > .jasmine-bar.jasmine-passed, .jasmine-alert > .jasmine-bar.skipped').innerText);
return 0;
}
});
phantom.exit(exitCode);
});
}
});
/*global config */
// Extra test dependencies // Extra test dependencies
config.paths.mock = "tests/mock"; config.paths.mock = "tests/mock";
config.paths.test_utils = "tests/utils"; config.paths['wait-until-promise'] = "node_modules/wait-until-promise/index";
config.paths['test-utils'] = "tests/utils";
config.paths.sinon = "node_modules/sinon/lib/sinon"; config.paths.sinon = "node_modules/sinon/lib/sinon";
config.paths.jasmine = "node_modules/jasmine-core/lib/jasmine-core/jasmine";
config.paths.transcripts = "converse-logs/converse-logs"; config.paths.transcripts = "converse-logs/converse-logs";
config.paths.jasmine = "node_modules/jasmine-core/lib/jasmine-core/jasmine";
config.paths.boot = "node_modules/jasmine-core/lib/jasmine-core/boot";
config.paths["jasmine-html"] = "node_modules/jasmine-core/lib/jasmine-core/jasmine-html"; config.paths["jasmine-html"] = "node_modules/jasmine-core/lib/jasmine-core/jasmine-html";
config.paths["console-runner"] = "node_modules/phantom-jasmine/lib/console-runner"; // config.paths["console-runner"] = "node_modules/phantom-jasmine/lib/console-runner";
config.shim.jasmine = {
exports: 'window.jasmineRequire'
};
config.shim['jasmine-html'] = { config.shim['jasmine-html'] = {
deps: ['jasmine'], deps: ['jasmine'],
exports: 'jasmine' exports: 'window.jasmineRequire'
}; };
config.shim.boot = {
deps: ['jasmine', 'jasmine-html'],
exports: 'window.jasmineRequire'
};
/*
config.shim['console-runner'] = { config.shim['console-runner'] = {
deps: ['jasmine'] deps: ['jasmine']
}; };
*/
require.config(config); require.config(config);
// Polyfill 'bind' which is not available in phantomjs < 2.0 // Polyfill 'bind' which is not available in phantomjs < 2.0
...@@ -35,13 +48,9 @@ if (!Function.prototype.bind) { ...@@ -35,13 +48,9 @@ if (!Function.prototype.bind) {
}; };
} }
require([ var specs = [
"jquery",
"mock",
"jasmine-html",
"sinon",
"console-runner",
//"spec/transcripts", //"spec/transcripts",
// "spec/profiling",
"spec/utils", "spec/utils",
"spec/converse", "spec/converse",
"spec/bookmarks", "spec/bookmarks",
...@@ -49,38 +58,31 @@ require([ ...@@ -49,38 +58,31 @@ require([
"spec/disco", "spec/disco",
"spec/protocol", "spec/protocol",
"spec/presence", "spec/presence",
"spec/eventemitter",
"spec/ping",
"spec/xmppstatus",
"spec/mam", "spec/mam",
"spec/otr", "spec/otr",
"spec/eventemitter",
"spec/controlbox", "spec/controlbox",
"spec/chatbox", "spec/chatbox",
"spec/chatroom", "spec/chatroom",
"spec/minchats", "spec/minchats",
"spec/notification", "spec/notification",
"spec/profiling", "spec/register"
"spec/ping", ];
"spec/register",
"spec/xmppstatus" require(['jquery', 'mock', 'boot', 'sinon', 'wait-until-promise'],
], function($, mock, jasmine, sinon) { function($, mock, jasmine, sinon, waitUntilPromise) {
window.sinon = sinon; window.sinon = sinon;
window.localStorage.clear(); window.waitUntilPromise = waitUntilPromise['default'];
window.sessionStorage.clear(); window.localStorage.clear();
// Jasmine stuff window.sessionStorage.clear();
var jasmineEnv = jasmine.getEnv();
var reporter; // Load the specs
if (/PhantomJS/.test(navigator.userAgent)) { require(specs, function () {
reporter = new jasmine.ConsoleReporter(); // Initialize the HTML Reporter and execute the environment (setup by `boot.js`)
window.console_reporter = reporter; // http://stackoverflow.com/questions/19240302/does-jasmine-2-0-really-not-work-with-require-js
jasmineEnv.addReporter(reporter); window.onload();
jasmineEnv.updateInterval = 0; });
} else {
reporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(reporter);
jasmineEnv.specFilter = function(spec) {
return reporter.specFilter(spec);
};
jasmineEnv.updateInterval = 0;
}
jasmineEnv.execute();
} }
); );
(function (root, factory) { (function (root, factory) {
define("test_utils", ['converse', 'mock'], factory); define(['converse', 'es6-promise', 'mock', 'wait-until-promise'], factory);
}(this, function (converse_api, mock) { }(this, function (converse_api, Promise, mock, waitUntilPromise) {
var _ = converse_api.env._;
var $ = converse_api.env.jQuery; var $ = converse_api.env.jQuery;
var $pres = converse_api.env.$pres; var $pres = converse_api.env.$pres;
var $iq = converse_api.env.$iq; var $iq = converse_api.env.$iq;
var Strophe = converse_api.env.Strophe; var Strophe = converse_api.env.Strophe;
var utils = {}; var utils = {};
if (typeof window.Promise === 'undefined') {
waitUntilPromise.setPromiseImplementation(Promise);
}
utils.waitUntil = waitUntilPromise['default'];
utils.createRequest = function (iq) { utils.createRequest = function (iq) {
iq = typeof iq.tree == "function" ? iq.tree() : iq; iq = typeof iq.tree == "function" ? iq.tree() : iq;
var req = new Strophe.Request(iq, function() {}); var req = new Strophe.Request(iq, function() {});
...@@ -27,28 +33,6 @@ ...@@ -27,28 +33,6 @@
return this; return this;
}; };
utils.removeAllChatBoxes = function () {
var i, chatbox, num_chatboxes = converse.chatboxes.models.length;
for (i=num_chatboxes-1; i>-1; i--) {
chatbox = converse.chatboxes.models[i];
converse.chatboxviews.get(chatbox.get('id')).close();
converse.chatboxviews.get(chatbox.get('id')).$el.remove();
}
converse.chatboxviews.get('controlbox').close();
converse.chatboxviews.get('controlbox').$el.remove();
return this;
};
utils.initConverse = function () {
converse._tearDown();
converse._initialize();
};
utils.initRoster = function () {
converse.roster.browserStorage._clear();
converse.initRoster();
};
utils.openControlBox = function () { utils.openControlBox = function () {
var $toggle = $(".toggle-controlbox"); var $toggle = $(".toggle-controlbox");
if (!$("#controlbox").is(':visible')) { if (!$("#controlbox").is(':visible')) {
...@@ -69,11 +53,6 @@ ...@@ -69,11 +53,6 @@
return this; return this;
}; };
utils.removeControlBox = function () {
converse.controlboxtoggle.show();
$('#controlbox').remove();
};
utils.openContactsPanel = function (converse) { utils.openContactsPanel = function (converse) {
this.openControlBox(converse); this.openControlBox(converse);
var cbview = converse.chatboxviews.get('controlbox'); var cbview = converse.chatboxviews.get('controlbox');
...@@ -157,14 +136,6 @@ ...@@ -157,14 +136,6 @@
converse.connection.sendIQ.restore(); converse.connection.sendIQ.restore();
}; };
utils.removeRosterContacts = function () {
var model;
while (converse.rosterview.model.length) {
model = converse.rosterview.model.pop();
converse.rosterview.model.remove(model);
}
};
utils.clearBrowserStorage = function () { utils.clearBrowserStorage = function () {
window.localStorage.clear(); window.localStorage.clear();
window.sessionStorage.clear(); window.sessionStorage.clear();
...@@ -184,7 +155,7 @@ ...@@ -184,7 +155,7 @@
* *
* These contacts are not grouped. See below. * These contacts are not grouped. See below.
*/ */
var names, jid; var names, jid, subscription, requesting, ask;
if (type === 'requesting') { if (type === 'requesting') {
names = mock.req_names; names = mock.req_names;
subscription = 'none'; subscription = 'none';
...@@ -206,13 +177,13 @@ ...@@ -206,13 +177,13 @@
.createContacts(converse, 'pending'); .createContacts(converse, 'pending');
return this; return this;
} else { } else {
throw "Need to specify the type of contact to create"; throw Error("Need to specify the type of contact to create");
} }
if (typeof length === 'undefined') { if (typeof length === 'undefined') {
length = names.length; length = names.length;
} }
for (i=0; i<length; i++) { for (var i=0; i<length; i++) {
jid = names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
if (!converse.roster.get(jid)) { if (!converse.roster.get(jid)) {
converse.roster.create({ converse.roster.create({
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment