michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: function test() { michael@0: requestLongerTimeout(2); // only debug builds seem to need more time... michael@0: waitForExplicitFinish(); michael@0: michael@0: let manifest = { // normal provider michael@0: name: "provider 1", michael@0: origin: "https://example.com", michael@0: sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html", michael@0: workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js", michael@0: iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png" michael@0: }; michael@0: michael@0: let postSubTest = function(cb) { michael@0: let chats = document.getElementById("pinnedchats"); michael@0: ok(chats.children.length == 0, "no chatty children left behind"); michael@0: cb(); michael@0: }; michael@0: runSocialTestWithProvider(manifest, function (finishcb) { michael@0: SocialSidebar.show(); michael@0: ok(SocialSidebar.provider, "sidebar provider exists"); michael@0: runSocialTests(tests, undefined, postSubTest, function() { michael@0: finishcb(); michael@0: }); michael@0: }); michael@0: } michael@0: michael@0: var tests = { michael@0: testTearoffChat: function(next) { michael@0: let chats = document.getElementById("pinnedchats"); michael@0: let chatTitle; michael@0: let port = SocialSidebar.provider.getWorkerPort(); michael@0: ok(port, "provider has a port"); michael@0: port.onmessage = function (e) { michael@0: let topic = e.data.topic; michael@0: switch (topic) { michael@0: case "got-sidebar-message": michael@0: port.postMessage({topic: "test-chatbox-open"}); michael@0: break; michael@0: case "got-chatbox-visibility": michael@0: // chatbox is open, lets detach. The new chat window will be caught in michael@0: // the window watcher below michael@0: let doc = chats.selectedChat.contentDocument; michael@0: // This message is (sometimes!) received a second time michael@0: // before we start our tests from the onCloseWindow michael@0: // callback. michael@0: if (doc.location == "about:blank") michael@0: return; michael@0: chatTitle = doc.title; michael@0: ok(chats.selectedChat.getAttribute("label") == chatTitle, michael@0: "the new chatbox should show the title of the chat window"); michael@0: let div = doc.createElement("div"); michael@0: div.setAttribute("id", "testdiv"); michael@0: div.setAttribute("test", "1"); michael@0: doc.body.appendChild(div); michael@0: let swap = document.getAnonymousElementByAttribute(chats.selectedChat, "anonid", "swap"); michael@0: swap.click(); michael@0: port.close(); michael@0: break; michael@0: case "got-chatbox-message": michael@0: ok(true, "got chatbox message"); michael@0: ok(e.data.result == "ok", "got chatbox windowRef result: "+e.data.result); michael@0: chats.selectedChat.toggle(); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: Services.wm.addListener({ michael@0: onWindowTitleChange: function() {}, michael@0: onCloseWindow: function(xulwindow) {}, michael@0: onOpenWindow: function(xulwindow) { michael@0: var domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) michael@0: .getInterface(Components.interfaces.nsIDOMWindow); michael@0: Services.wm.removeListener(this); michael@0: // wait for load to ensure the window is ready for us to test michael@0: domwindow.addEventListener("load", function _load(event) { michael@0: let doc = domwindow.document; michael@0: if (event.target != doc) michael@0: return; michael@0: michael@0: domwindow.removeEventListener("load", _load, false); michael@0: michael@0: domwindow.addEventListener("unload", function _close(event) { michael@0: if (event.target != doc) michael@0: return; michael@0: domwindow.removeEventListener("unload", _close, false); michael@0: info("window has been closed"); michael@0: waitForCondition(function() { michael@0: return chats.selectedChat && chats.selectedChat.contentDocument && michael@0: chats.selectedChat.contentDocument.readyState == "complete"; michael@0: },function () { michael@0: ok(chats.selectedChat, "should have a chatbox in our window again"); michael@0: ok(chats.selectedChat.getAttribute("label") == chatTitle, michael@0: "the new chatbox should show the title of the chat window again"); michael@0: let testdiv = chats.selectedChat.contentDocument.getElementById("testdiv"); michael@0: is(testdiv.getAttribute("test"), "2", "docshell should have been swapped"); michael@0: chats.selectedChat.close(); michael@0: waitForCondition(function() { michael@0: return chats.children.length == 0; michael@0: },function () { michael@0: next(); michael@0: }); michael@0: }); michael@0: }, false); michael@0: michael@0: is(doc.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened"); michael@0: // window is loaded, but the docswap does not happen until after load, michael@0: // and we have no event to wait on, so we'll wait for document state michael@0: // to be ready michael@0: let chatbox = doc.getElementById("chatter"); michael@0: waitForCondition(function() { michael@0: return chats.selectedChat == null && michael@0: chatbox.contentDocument && michael@0: chatbox.contentDocument.readyState == "complete"; michael@0: },function() { michael@0: ok(chatbox.getAttribute("label") == chatTitle, michael@0: "detached window should show the title of the chat window"); michael@0: let testdiv = chatbox.contentDocument.getElementById("testdiv"); michael@0: is(testdiv.getAttribute("test"), "1", "docshell should have been swapped"); michael@0: testdiv.setAttribute("test", "2"); michael@0: // swap the window back to the chatbar michael@0: let swap = doc.getAnonymousElementByAttribute(chatbox, "anonid", "swap"); michael@0: swap.click(); michael@0: }, domwindow); michael@0: }, false); michael@0: } michael@0: }); michael@0: michael@0: port.postMessage({topic: "test-init", data: { id: 1 }}); michael@0: }, michael@0: michael@0: testCloseOnLogout: function(next) { michael@0: let chats = document.getElementById("pinnedchats"); michael@0: const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html"; michael@0: let port = SocialSidebar.provider.getWorkerPort(); michael@0: ok(port, "provider has a port"); michael@0: port.postMessage({topic: "test-init"}); michael@0: port.onmessage = function (e) { michael@0: let topic = e.data.topic; michael@0: switch (topic) { michael@0: case "got-chatbox-visibility": michael@0: // chatbox is open, lets detach. The new chat window will be caught in michael@0: // the window watcher below michael@0: let doc = chats.selectedChat.contentDocument; michael@0: // This message is (sometimes!) received a second time michael@0: // before we start our tests from the onCloseWindow michael@0: // callback. michael@0: if (doc.location == "about:blank") michael@0: return; michael@0: info("chatbox is open, detach from window"); michael@0: let swap = document.getAnonymousElementByAttribute(chats.selectedChat, "anonid", "swap"); michael@0: swap.click(); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: Services.wm.addListener({ michael@0: onWindowTitleChange: function() {}, michael@0: onCloseWindow: function(xulwindow) {}, michael@0: onOpenWindow: function(xulwindow) { michael@0: let domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) michael@0: .getInterface(Components.interfaces.nsIDOMWindow); michael@0: Services.wm.removeListener(this); michael@0: // wait for load to ensure the window is ready for us to test, make sure michael@0: // we're not getting called for about:blank michael@0: domwindow.addEventListener("load", function _load(event) { michael@0: let doc = domwindow.document; michael@0: if (event.target != doc) michael@0: return; michael@0: domwindow.removeEventListener("load", _load, false); michael@0: michael@0: domwindow.addEventListener("unload", function _close(event) { michael@0: if (event.target != doc) michael@0: return; michael@0: domwindow.removeEventListener("unload", _close, false); michael@0: ok(true, "window has been closed"); michael@0: next(); michael@0: }, false); michael@0: michael@0: is(doc.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened"); michael@0: // window is loaded, but the docswap does not happen until after load, michael@0: // and we have no event to wait on, so we'll wait for document state michael@0: // to be ready michael@0: let chatbox = doc.getElementById("chatter"); michael@0: waitForCondition(function() { michael@0: return chats.children.length == 0 && michael@0: chatbox.contentDocument && michael@0: chatbox.contentDocument.readyState == "complete"; michael@0: },function() { michael@0: // logout, we should get unload next michael@0: port.postMessage({topic: "test-logout"}); michael@0: port.close(); michael@0: }, domwindow); michael@0: michael@0: }, false); michael@0: } michael@0: }); michael@0: michael@0: port.postMessage({topic: "test-worker-chat", data: chatUrl}); michael@0: }, michael@0: michael@0: testReattachTwice: function(next) { michael@0: let chats = document.getElementById("pinnedchats"); michael@0: const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html"; michael@0: let chatBoxCount = 0, reattachCount = 0; michael@0: let port = SocialSidebar.provider.getWorkerPort(); michael@0: ok(port, "provider has a port"); michael@0: port.postMessage({topic: "test-init"}); michael@0: port.onmessage = function (e) { michael@0: let topic = e.data.topic; michael@0: switch (topic) { michael@0: case "got-chatbox-visibility": michael@0: // chatbox is open, lets detach. The new chat window will be caught in michael@0: // the window watcher below michael@0: let doc = chats.selectedChat.contentDocument; michael@0: // This message is (sometimes!) received a second time michael@0: // before we start our tests from the onCloseWindow michael@0: // callback. michael@0: if (doc.location == "about:blank") michael@0: return; michael@0: if (++chatBoxCount != 2) { michael@0: // open the second chat window michael@0: port.postMessage({topic: "test-worker-chat", data: chatUrl + "?id=2"}); michael@0: return; michael@0: } michael@0: info("chatbox is open, detach from window"); michael@0: let chat1 = chats.firstChild; michael@0: let chat2 = chat1.nextSibling; michael@0: document.getAnonymousElementByAttribute(chat1, "anonid", "swap").click(); michael@0: document.getAnonymousElementByAttribute(chat2, "anonid", "swap").click(); michael@0: break; michael@0: } michael@0: }; michael@0: michael@0: let firstChatWindowDoc; michael@0: Services.wm.addListener({ michael@0: onWindowTitleChange: function() {}, michael@0: onCloseWindow: function(xulwindow) {}, michael@0: onOpenWindow: function(xulwindow) { michael@0: let listener = this; michael@0: let domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) michael@0: .getInterface(Components.interfaces.nsIDOMWindow); michael@0: // wait for load to ensure the window is ready for us to test, make sure michael@0: // we're not getting called for about:blank michael@0: domwindow.addEventListener("load", function _load(event) { michael@0: let doc = domwindow.document; michael@0: if (event.target != doc) michael@0: return; michael@0: domwindow.removeEventListener("load", _load, false); michael@0: michael@0: domwindow.addEventListener("unload", function _close(event) { michael@0: if (event.target != doc) michael@0: return; michael@0: domwindow.removeEventListener("unload", _close, false); michael@0: ok(true, "window has been closed"); michael@0: waitForCondition(function() { michael@0: return chats.selectedChat && chats.selectedChat.contentDocument && michael@0: chats.selectedChat.contentDocument.readyState == "complete"; michael@0: }, function () { michael@0: ++reattachCount; michael@0: if (reattachCount == 1) { michael@0: info("reattaching second chat window"); michael@0: let chatbox = firstChatWindowDoc.getElementById("chatter"); michael@0: firstChatWindowDoc.getAnonymousElementByAttribute(chatbox, "anonid", "swap").click(); michael@0: firstChatWindowDoc = null; michael@0: } michael@0: else if (reattachCount == 2) { michael@0: is(chats.children.length, 2, "both chat windows should be reattached"); michael@0: chats.removeAll(); michael@0: waitForCondition(() => chats.children.length == 0, function () { michael@0: info("no chat window left"); michael@0: is(chats.chatboxForURL.size, 0, "chatboxForURL map should be empty"); michael@0: next(); michael@0: }); michael@0: } michael@0: }, "waited too long for the window to reattach"); michael@0: }, false); michael@0: michael@0: is(doc.documentElement.getAttribute("windowtype"), "Social:Chat", "Social:Chat window opened"); michael@0: if (!firstChatWindowDoc) { michael@0: firstChatWindowDoc = doc; michael@0: return; michael@0: } michael@0: Services.wm.removeListener(listener); michael@0: michael@0: // window is loaded, but the docswap does not happen until after load, michael@0: // and we have no event to wait on, so we'll wait for document state michael@0: // to be ready michael@0: let chatbox = doc.getElementById("chatter"); michael@0: waitForCondition(function() { michael@0: return chats.children.length == 0 && michael@0: chatbox.contentDocument && michael@0: chatbox.contentDocument.readyState == "complete"; michael@0: },function() { michael@0: info("reattaching chat window"); michael@0: doc.getAnonymousElementByAttribute(chatbox, "anonid", "swap").click(); michael@0: }, "waited too long for the chat window to be detached"); michael@0: michael@0: }, false); michael@0: } michael@0: }); michael@0: michael@0: port.postMessage({topic: "test-worker-chat", data: chatUrl + "?id=1"}); michael@0: } michael@0: };