$(document).ready(function () { module("JIDs"); test("Normal JID", function () { var jid = "darcy@pemberley.lit/library"; equal(Strophe.getNodeFromJid(jid), "darcy", "Node should be 'darcy'"); equal(Strophe.getDomainFromJid(jid), "pemberley.lit", "Domain should be 'pemberley.lit'"); equal(Strophe.getResourceFromJid(jid), "library", "Node should be 'library'"); equal(Strophe.getBareJidFromJid(jid), "darcy@pemberley.lit", "Bare JID should be 'darcy@pemberley.lit'"); }); test("Weird node (unescaped)", function () { var jid = "darcy@netherfield.lit@pemberley.lit/library"; equal(Strophe.getNodeFromJid(jid), "darcy", "Node should be 'darcy'"); equal(Strophe.getDomainFromJid(jid), "netherfield.lit@pemberley.lit", "Domain should be 'netherfield.lit@pemberley.lit'"); equal(Strophe.getResourceFromJid(jid), "library", "Resource should be 'library'"); equal(Strophe.getBareJidFromJid(jid), "darcy@netherfield.lit@pemberley.lit", "Bare JID should be 'darcy@netherfield.lit@pemberley.lit'"); }); test("Weird node (escaped)", function () { var escapedNode = Strophe.escapeNode("darcy@netherfield.lit"); var jid = escapedNode + "@pemberley.lit/library"; equal(Strophe.getNodeFromJid(jid), "darcy\\40netherfield.lit", "Node should be 'darcy\\40netherfield.lit'"); equal(Strophe.getDomainFromJid(jid), "pemberley.lit", "Domain should be 'pemberley.lit'"); equal(Strophe.getResourceFromJid(jid), "library", "Resource should be 'library'"); equal(Strophe.getBareJidFromJid(jid), "darcy\\40netherfield.lit@pemberley.lit", "Bare JID should be 'darcy\\40netherfield.lit@pemberley.lit'"); }); test("Weird resource", function () { var jid = "books@chat.pemberley.lit/darcy@pemberley.lit/library"; equal(Strophe.getNodeFromJid(jid), "books", "Node should be 'books'"); equal(Strophe.getDomainFromJid(jid), "chat.pemberley.lit", "Domain should be 'chat.pemberley.lit'"); equal(Strophe.getResourceFromJid(jid), "darcy@pemberley.lit/library", "Resource should be 'darcy@pemberley.lit/library'"); equal(Strophe.getBareJidFromJid(jid), "books@chat.pemberley.lit", "Bare JID should be 'books@chat.pemberley.lit'"); }); module("Builder"); test("Correct namespace (#32)", function () { var stanzas = [new Strophe.Builder("message", {foo: "asdf"}).tree(), $build("iq", {}).tree(), $pres().tree()]; $.each(stanzas, function () { equal($(this).attr('xmlns'), Strophe.NS.CLIENT, "Namespace should be '" + Strophe.NS.CLIENT + "'"); }); }); test("send() accepts Builders (#27)", function () { var stanza = $pres(); var conn = new Strophe.Connection(""); // fake connection callback to avoid errors conn.connect_callback = function () {}; ok(conn._data.length === 0, "Output queue is clean"); try { conn.send(stanza); } catch (e) {} ok(conn._data.length === 1, "Output queue contains an element"); }); test("send() does not accept strings", function () { var stanza = ""; var conn = new Strophe.Connection(""); // fake connection callback to avoid errors conn.connect_callback = function () {}; expect(1); try { conn.send(stanza); } catch (e) { equal(e.name, "StropheError", "send() should throw exception"); } }); test("Builder with XML attribute escaping test", function () { var text = ""; var expected = ""; var pres = $pres({to: text}); equal(pres.toString(), expected, "< should be escaped"); text = "foo&bar"; expected = ""; pres = $pres({to: text}); equal(pres.toString(), expected, "& should be escaped"); }); test("c() accepts text and passes it to xmlElement", function () { var pres = $pres({from: "darcy@pemberley.lit", to: "books@chat.pemberley.lit"}) .c("nick", {xmlns: "http://jabber.org/protocol/nick"}, "Darcy"); var expected = "Darcy"; equal(pres.toString(), expected, "'Darcy' should be a child of "); }); module("XML"); test("XML escaping test", function () { var text = "s & p"; var textNode = Strophe.xmlTextNode(text); equal(Strophe.getText(textNode), "s & p", "should be escaped"); var text0 = "s < & > p"; var textNode0 = Strophe.xmlTextNode(text0); equal(Strophe.getText(textNode0), "s < & > p", "should be escaped"); var text1 = "s's or \"p\""; var textNode1 = Strophe.xmlTextNode(text1); equal(Strophe.getText(textNode1), "s's or "p"", "should be escaped"); var text2 = "]]>"; var textNode2 = Strophe.xmlTextNode(text2); equal(Strophe.getText(textNode2), "<![CDATA[<foo>]]>", "should be escaped"); var text3 = "]]>"; var textNode3 = Strophe.xmlTextNode(text3); equal(Strophe.getText(textNode3), "<![CDATA[]]]]><![CDATA[>]]>", "should be escaped"); var text4 = "<foo>]]>"; var textNode4 = Strophe.xmlTextNode(text4); equal(Strophe.getText(textNode4), "&lt;foo&gt;<![CDATA[<foo>]]>", "should be escaped"); }); test("XML element creation", function () { var elem = Strophe.xmlElement("message"); equal(elem.tagName, "message", "Element name should be the same"); }); test("copyElement() double escape bug", function() { var cloned = Strophe.copyElement(Strophe.xmlGenerator() .createTextNode('<><>')); equal(cloned.nodeValue, '<><>'); }); test("XML serializing", function() { var parser = new DOMParser(); // Attributes var element1 = parser.parseFromString("bar","text/xml").documentElement; equal(Strophe.serialize(element1), "bar", "should be serialized"); var element2 = parser.parseFromString("bar","text/xml").documentElement; equal(Strophe.serialize(element2), "bar", "should be serialized"); // Escaping values var element3 = parser.parseFromString("a > 'b' & "b" < c","text/xml").documentElement; equal(Strophe.serialize(element3), "a > 'b' & "b" < c", "should be serialized"); // Escaping attributes var element4 = parser.parseFromString("bar","text/xml").documentElement; equal(Strophe.serialize(element4), "bar", "should be serialized"); var element5 = parser.parseFromString(" "b"\">bar","text/xml").documentElement; equal(Strophe.serialize(element5), "bar", "should be serialized"); // Empty elements var element6 = parser.parseFromString("","text/xml").documentElement; equal(Strophe.serialize(element6), "", "should be serialized"); // Children var element7 = parser.parseFromString("ab","text/xml").documentElement; equal(Strophe.serialize(element7), "ab", "should be serialized"); var element8 = parser.parseFromString("abcd","text/xml").documentElement; equal(Strophe.serialize(element8), "abcd", "should be serialized"); // CDATA var element9 = parser.parseFromString("]]>","text/xml").documentElement; equal(Strophe.serialize(element9), "]]>", "should be serialized"); var element10 = parser.parseFromString("]]>","text/xml").documentElement; equal(Strophe.serialize(element10), "]]>", "should be serialized"); var element11 = parser.parseFromString("<foo>]]>","text/xml").documentElement; equal(Strophe.serialize(element11), "<foo>]]>", "should be serialized"); }); module("Handler"); test("Full JID matching", function () { var elem = $msg({from: 'darcy@pemberley.lit/library'}).tree(); var hand = new Strophe.Handler(null, null, null, null, null, 'darcy@pemberley.lit/library'); equal(hand.isMatch(elem), true, "Full JID should match"); hand = new Strophe.Handler(null, null, null, null, null, 'darcy@pemberley.lit') equal(hand.isMatch(elem), false, "Bare JID shouldn't match"); }); test("Bare JID matching", function () { var elem = $msg({from: 'darcy@pemberley.lit/library'}).tree(); var hand = new Strophe.Handler(null, null, null, null, null, 'darcy@pemberley.lit/library', {matchBare: true}); equal(hand.isMatch(elem), true, "Full JID should match"); hand = new Strophe.Handler(null, null, null, null, null, 'darcy@pemberley.lit', {matchBare: true}); equal(hand.isMatch(elem), true, "Bare JID should match"); }); module("Misc"); test("Quoting strings", function () { var input = '"beep \\40"'; var saslmd5 = new Strophe.SASLMD5(); var output = saslmd5._quote(input); equal(output, "\"\\\"beep \\\\40\\\"\"", "string should be quoted and escaped"); }); test("Function binding", function () { var spy = sinon.spy(); var obj = {}; var arg1 = "foo"; var arg2 = "bar"; var arg3 = "baz"; var f = spy.bind(obj, arg1, arg2); f(arg3); equal(spy.called, true, "bound function should be called"); equal(spy.calledOn(obj), true, "bound function should have correct context"); equal(spy.alwaysCalledWithExactly(arg1, arg2, arg3), true, "bound function should get all arguments"); }); module("XHR error handling"); // Note that these tests are pretty dependent on the actual code. test("Aborted requests do nothing", function () { Strophe.Connection.prototype._onIdle = function () {}; var conn = new Strophe.Connection("http://fake"); // simulate a finished but aborted request var req = {id: 43, sends: 1, xhr: { readyState: 4 }, abort: true}; conn._requests = [req]; var spy = sinon.spy(); conn._proto._onRequestStateChange(spy, req); equal(req.abort, false, "abort flag should be toggled"); equal(conn._requests.length, 1, "_requests should be same length"); equal(spy.called, false, "callback should not be called"); }); test("Incomplete requests do nothing", function () { Strophe.Connection.prototype._onIdle = function () {}; var conn = new Strophe.Connection("http://fake"); // simulate a finished but aborted request var req = {id: 44, sends: 1, xhr: { readyState: 3 }}; conn._requests = [req]; var spy = sinon.spy(); conn._proto._onRequestStateChange(spy, req); equal(conn._requests.length, 1, "_requests should be same length"); equal(spy.called, false, "callback should not be called"); }); module("SASL Mechanisms"); test("SASL Plain Auth", function () { var conn = {pass: "password", authcid: "user", authzid: "user@xmpp.org"}; ok(Strophe.SASLPlain.test(conn), "plain should pass the test"); var saslplain = new Strophe.SASLPlain(); saslplain.onStart(conn); var response = saslplain.onChallenge(conn, null); equal(response, [conn.authzid, conn.authcid, conn.pass].join("\u0000"), "checking plain auth challenge"); saslplain.onSuccess(); }); test("SASL SCRAM-SHA-1 Auth", function () { var conn = {pass: "pencil", authcid: "user", authzid: "user@xmpp.org", _sasl_data: []}; ok(Strophe.SASLSHA1.test(conn), "sha-1 should pass the test"); var saslsha1 = new Strophe.SASLSHA1(); saslsha1.onStart(conn); // test taken from example section on: // URL: http://tools.ietf.org/html/rfc5802#section-5 var response = saslsha1.onChallenge(conn, null, "fyko+d2lbbFgONRv9qkxdawL"); equal(response, "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL", "checking first auth challenge"); var response = saslsha1.onChallenge(conn, "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096"); equal(response, "c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=", "checking second auth challenge"); saslsha1.onSuccess(); }); test("SASL DIGEST-MD-5 Auth", function () { var conn = {pass: "secret", authcid: "chris", authzid: "user@xmpp.org", servtype: "imap", domain: "elwood.innosoft.com", _sasl_data: []}; ok(Strophe.SASLMD5.test(conn), "md-5 should pass the test"); var saslmd5 = new Strophe.SASLMD5(); saslmd5.onStart(conn); // test taken from example section on: // URL: http://www.ietf.org/rfc/rfc2831.txt var response = saslmd5.onChallenge(conn, "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8", "OA6MHXh6VqTrRk"); equal(response, "charset=utf-8,username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",nc=00000001,cnonce=\"OA6MHXh6VqTrRk\",digest-uri=\"imap/elwood.innosoft.com\",response=d388dad90d4bbd760a152321f2143af7,qop=auth", "checking first auth challenge"); var response = saslmd5.onChallenge(conn, "rspauth=ea40f60335c427b5527b84dbabcdfffd"); equal(response, "", "checking second auth challenge"); saslmd5.onSuccess(); }); });