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: // tests the translation infobar, using a fake 'Translation' implementation. michael@0: michael@0: Components.utils.import("resource:///modules/translation/Translation.jsm"); michael@0: michael@0: function waitForCondition(condition, nextTest, errorMsg) { michael@0: var tries = 0; michael@0: var interval = setInterval(function() { michael@0: if (tries >= 30) { michael@0: ok(false, errorMsg); michael@0: moveOn(); michael@0: } michael@0: var conditionPassed; michael@0: try { michael@0: conditionPassed = condition(); michael@0: } catch (e) { michael@0: ok(false, e + "\n" + e.stack); michael@0: conditionPassed = false; michael@0: } michael@0: if (conditionPassed) { michael@0: moveOn(); michael@0: } michael@0: tries++; michael@0: }, 100); michael@0: var moveOn = function() { clearInterval(interval); nextTest(); }; michael@0: } michael@0: michael@0: var TranslationStub = { michael@0: translate: function(aFrom, aTo) { michael@0: this.state = this.STATE_TRANSLATING; michael@0: this.translatedFrom = aFrom; michael@0: this.translatedTo = aTo; michael@0: }, michael@0: michael@0: _reset: function() { michael@0: this.translatedFrom = ""; michael@0: this.translatedTo = ""; michael@0: }, michael@0: michael@0: failTranslation: function() { michael@0: this.state = this.STATE_ERROR; michael@0: this._reset(); michael@0: }, michael@0: michael@0: finishTranslation: function() { michael@0: this.showTranslatedContent(); michael@0: this.state = this.STATE_TRANSLATED; michael@0: this._reset(); michael@0: } michael@0: }; michael@0: michael@0: function showTranslationUI(aDetectedLanguage) { michael@0: let browser = gBrowser.selectedBrowser; michael@0: Translation.languageDetected(browser, aDetectedLanguage); michael@0: let ui = browser.translationUI; michael@0: for (let name of ["translate", "_reset", "failTranslation", "finishTranslation"]) michael@0: ui[name] = TranslationStub[name]; michael@0: return ui.notificationBox.getNotificationWithValue("translation"); michael@0: } michael@0: michael@0: function test() { michael@0: waitForExplicitFinish(); michael@0: michael@0: let tab = gBrowser.addTab(); michael@0: gBrowser.selectedTab = tab; michael@0: tab.linkedBrowser.addEventListener("load", function onload() { michael@0: tab.linkedBrowser.removeEventListener("load", onload, true); michael@0: TranslationStub.browser = gBrowser.selectedBrowser; michael@0: registerCleanupFunction(function () { michael@0: gBrowser.removeTab(tab); michael@0: }); michael@0: run_tests(() => { michael@0: finish(); michael@0: }); michael@0: }, true); michael@0: michael@0: content.location = "data:text/plain,test page"; michael@0: } michael@0: michael@0: function checkURLBarIcon(aExpectTranslated = false) { michael@0: is(!PopupNotifications.getNotification("translate"), aExpectTranslated, michael@0: "translate icon " + (aExpectTranslated ? "not " : "") + "shown"); michael@0: is(!!PopupNotifications.getNotification("translated"), aExpectTranslated, michael@0: "translated icon " + (aExpectTranslated ? "" : "not ") + "shown"); michael@0: } michael@0: michael@0: function run_tests(aFinishCallback) { michael@0: info("Show an info bar saying the current page is in French"); michael@0: let notif = showTranslationUI("fr"); michael@0: is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation"); michael@0: is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed"); michael@0: checkURLBarIcon(); michael@0: michael@0: info("Click the 'Translate' button"); michael@0: notif._getAnonElt("translate").click(); michael@0: is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state"); michael@0: ok(!!notif.translation.translatedFrom, "Translation.translate has been called"); michael@0: is(notif.translation.translatedFrom, "fr", "from language correct"); michael@0: is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct"); michael@0: checkURLBarIcon(); michael@0: michael@0: info("Make the translation fail and check we are in the error state."); michael@0: notif.translation.failTranslation(); michael@0: is(notif.state, notif.translation.STATE_ERROR, "infobar in the error state"); michael@0: checkURLBarIcon(); michael@0: michael@0: info("Click the try again button"); michael@0: notif._getAnonElt("tryAgain").click(); michael@0: is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state"); michael@0: ok(!!notif.translation.translatedFrom, "Translation.translate has been called"); michael@0: is(notif.translation.translatedFrom, "fr", "from language correct"); michael@0: is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct"); michael@0: checkURLBarIcon(); michael@0: michael@0: info("Make the translation succeed and check we are in the 'translated' state."); michael@0: notif.translation.finishTranslation(); michael@0: is(notif.state, notif.translation.STATE_TRANSLATED, "infobar in the translated state"); michael@0: checkURLBarIcon(true); michael@0: michael@0: info("Test 'Show original' / 'Show Translation' buttons."); michael@0: // First check 'Show Original' is visible and 'Show Translation' is hidden. michael@0: ok(!notif._getAnonElt("showOriginal").hidden, "'Show Original' button visible"); michael@0: ok(notif._getAnonElt("showTranslation").hidden, "'Show Translation' button hidden"); michael@0: // Click the button. michael@0: notif._getAnonElt("showOriginal").click(); michael@0: // Check that the url bar icon shows the original content is displayed. michael@0: checkURLBarIcon(); michael@0: // And the 'Show Translation' button is now visible. michael@0: ok(notif._getAnonElt("showOriginal").hidden, "'Show Original' button hidden"); michael@0: ok(!notif._getAnonElt("showTranslation").hidden, "'Show Translation' button visible"); michael@0: // Click the 'Show Translation' button michael@0: notif._getAnonElt("showTranslation").click(); michael@0: // Check that the url bar icon shows the page is translated. michael@0: checkURLBarIcon(true); michael@0: // Check that the 'Show Original' button is visible again. michael@0: ok(!notif._getAnonElt("showOriginal").hidden, "'Show Original' button visible"); michael@0: ok(notif._getAnonElt("showTranslation").hidden, "'Show Translation' button hidden"); michael@0: michael@0: info("Check that changing the source language causes a re-translation"); michael@0: let from = notif._getAnonElt("fromLanguage"); michael@0: from.value = "es"; michael@0: from.doCommand(); michael@0: is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state"); michael@0: ok(!!notif.translation.translatedFrom, "Translation.translate has been called"); michael@0: is(notif.translation.translatedFrom, "es", "from language correct"); michael@0: is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "to language correct"); michael@0: // We want to show the 'translated' icon while re-translating, michael@0: // because we are still displaying the previous translation. michael@0: checkURLBarIcon(true); michael@0: notif.translation.finishTranslation(); michael@0: checkURLBarIcon(true); michael@0: michael@0: info("Check that changing the target language causes a re-translation"); michael@0: let to = notif._getAnonElt("toLanguage"); michael@0: to.value = "pl"; michael@0: to.doCommand(); michael@0: is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state"); michael@0: ok(!!notif.translation.translatedFrom, "Translation.translate has been called"); michael@0: is(notif.translation.translatedFrom, "es", "from language correct"); michael@0: is(notif.translation.translatedTo, "pl", "to language correct"); michael@0: checkURLBarIcon(true); michael@0: notif.translation.finishTranslation(); michael@0: checkURLBarIcon(true); michael@0: michael@0: // Cleanup. michael@0: notif.close(); michael@0: michael@0: info("Reopen the info bar to check that it's possible to override the detected language."); michael@0: notif = showTranslationUI("fr"); michael@0: is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation"); michael@0: is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed"); michael@0: // Change the language and click 'Translate' michael@0: notif._getAnonElt("detectedLanguage").value = "ja"; michael@0: notif._getAnonElt("translate").click(); michael@0: is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state"); michael@0: ok(!!notif.translation.translatedFrom, "Translation.translate has been called"); michael@0: is(notif.translation.translatedFrom, "ja", "from language correct"); michael@0: notif.close(); michael@0: michael@0: info("Reopen to check the 'Not Now' button closes the notification."); michael@0: notif = showTranslationUI("fr"); michael@0: let notificationBox = gBrowser.getNotificationBox(); michael@0: ok(!!notificationBox.getNotificationWithValue("translation"), "there's a 'translate' notification"); michael@0: notif._getAnonElt("notNow").click(); michael@0: ok(!notificationBox.getNotificationWithValue("translation"), "no 'translate' notification after clicking 'not now'"); michael@0: michael@0: info("Check that clicking the url bar icon reopens the info bar"); michael@0: checkURLBarIcon(); michael@0: // Clicking the anchor element causes a 'showing' event to be sent michael@0: // asynchronously to our callback that will then show the infobar. michael@0: PopupNotifications.getNotification("translate").anchorElement.click(); michael@0: waitForCondition(() => !!notificationBox.getNotificationWithValue("translation"), () => { michael@0: ok(!!notificationBox.getNotificationWithValue("translation"), michael@0: "there's a 'translate' notification"); michael@0: aFinishCallback(); michael@0: }, "timeout waiting for the info bar to reappear"); michael@0: }