diff options
Diffstat (limited to 'comm/mail/test/browser/composition/browser_spelling.js')
-rw-r--r-- | comm/mail/test/browser/composition/browser_spelling.js | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/comm/mail/test/browser/composition/browser_spelling.js b/comm/mail/test/browser/composition/browser_spelling.js new file mode 100644 index 0000000000..86a1ba9c84 --- /dev/null +++ b/comm/mail/test/browser/composition/browser_spelling.js @@ -0,0 +1,311 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ + +var { close_compose_window, open_compose_new_mail } = ChromeUtils.import( + "resource://testing-common/mozmill/ComposeHelpers.jsm" +); +var { maybeOnSpellCheck } = ChromeUtils.importESModule( + "resource://testing-common/AsyncSpellCheckTestHelper.sys.mjs" +); + +async function checkMisspelledWords(editor, ...words) { + await new Promise(resolve => maybeOnSpellCheck({ editor }, resolve)); + + let selection = editor.selectionController.getSelection( + Ci.nsISelectionController.SELECTION_SPELLCHECK + ); + Assert.equal( + selection.rangeCount, + words.length, + "correct number of misspellings" + ); + for (let i = 0; i < words.length; i++) { + Assert.equal(selection.getRangeAt(i).toString(), words[i]); + } + return selection; +} + +add_task(async function () { + // Install en-NZ dictionary. + + let dictionary = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + dictionary.initWithPath(getTestFilePath("data/en_NZ")); + + let hunspell = Cc["@mozilla.org/spellchecker/engine;1"].getService( + Ci.mozISpellCheckingEngine + ); + hunspell.addDirectory(dictionary); + + // Open a compose window and write a message. + + let cwc = open_compose_new_mail(); + let composeWindow = cwc.window; + let composeDocument = composeWindow.document; + + cwc.window.document.getElementById("msgSubject").focus(); + EventUtils.sendString( + "I went to the harbor in an aluminium boat", + cwc.window + ); + cwc.window.document.getElementById("messageEditor").focus(); + EventUtils.sendString("I maneuvered to the center.\n", cwc.window); + cwc.window.document.getElementById("messageEditor").focus(); + EventUtils.sendString( + "The sky was the colour of ochre and the stars shone like jewelry.\n", + cwc.window + ); + + // Check initial spelling. + + let subjectEditor = composeDocument.getElementById("msgSubject").editor; + let editorBrowser = composeWindow.GetCurrentEditorElement(); + let bodyEditor = composeWindow.GetCurrentEditor(); + let saveButton = composeDocument.getElementById("button-save"); + + await checkMisspelledWords(subjectEditor, "aluminium"); + await checkMisspelledWords(bodyEditor, "colour", "ochre"); + + // Check menu items are displayed correctly. + + let shownPromise, hiddenPromise; + let contextMenu = composeDocument.getElementById("msgComposeContext"); + let contextMenuEnabled = composeDocument.getElementById("spellCheckEnable"); + let optionsMenu = composeDocument.getElementById("optionsMenu"); + let optionsMenuEnabled = composeDocument.getElementById( + "menu_inlineSpellCheck" + ); + + if (AppConstants.platform != "macosx") { + shownPromise = BrowserTestUtils.waitForEvent(optionsMenu, "popupshown"); + EventUtils.synthesizeMouseAtCenter(optionsMenu, {}, composeWindow); + await shownPromise; + Assert.equal( + optionsMenuEnabled.getAttribute("checked"), + "true", + "options menu item is checked" + ); + hiddenPromise = BrowserTestUtils.waitForEvent(optionsMenu, "popuphidden"); + EventUtils.synthesizeKey("VK_ESCAPE", {}, composeWindow); + await hiddenPromise; + } + + shownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + await BrowserTestUtils.synthesizeMouseAtCenter( + "body", + { type: "contextmenu" }, + editorBrowser + ); + await shownPromise; + Assert.equal( + contextMenuEnabled.getAttribute("checked"), + "true", + "context menu item is checked" + ); + + // Disable the spell checker. + + hiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden"); + contextMenu.activateItem(contextMenuEnabled); + await hiddenPromise; + + await checkMisspelledWords(subjectEditor); + await checkMisspelledWords(bodyEditor); + + // Save the message. The spell checking state shouldn't change. + + EventUtils.synthesizeMouseAtCenter(saveButton, {}, composeWindow); + // Clicking the button sets gWindowLocked to true synchronously, so if + // gWindowLocked is false, we know that saving has completed. + await TestUtils.waitForCondition( + () => !composeWindow.gWindowLocked, + "window unlocked after saving" + ); + + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(resolve => setTimeout(resolve, 500)); + + await checkMisspelledWords(subjectEditor); + await checkMisspelledWords(bodyEditor); + + // Check menu items are displayed correctly. + + if (AppConstants.platform != "macosx") { + shownPromise = BrowserTestUtils.waitForEvent(optionsMenu, "popupshown"); + EventUtils.synthesizeMouseAtCenter(optionsMenu, {}, composeWindow); + await shownPromise; + Assert.ok( + !optionsMenuEnabled.hasAttribute("checked"), + "options menu item is not checked" + ); + hiddenPromise = BrowserTestUtils.waitForEvent(optionsMenu, "popuphidden"); + EventUtils.synthesizeKey("VK_ESCAPE", {}, composeWindow); + await hiddenPromise; + } + + shownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + await BrowserTestUtils.synthesizeMouseAtCenter( + "body", + { type: "contextmenu" }, + editorBrowser + ); + await shownPromise; + Assert.equal( + contextMenuEnabled.getAttribute("checked"), + "false", + "context menu item is not checked" + ); + + // Enable the spell checker. + + hiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden"); + contextMenu.activateItem(contextMenuEnabled); + await hiddenPromise; + + await checkMisspelledWords(subjectEditor, "aluminium"); + await checkMisspelledWords(bodyEditor, "colour", "ochre"); + + // Save the message. The spell checking state shouldn't change. + + EventUtils.synthesizeMouseAtCenter(saveButton, {}, composeWindow); + // Clicking the button sets gWindowLocked to true synchronously, so if + // gWindowLocked is false, we know that saving has completed. + await TestUtils.waitForCondition( + () => !composeWindow.gWindowLocked, + "window unlocked after saving" + ); + + await checkMisspelledWords(subjectEditor, "aluminium"); + await checkMisspelledWords(bodyEditor, "colour", "ochre"); + + // Add language. + + let statusButton = composeDocument.getElementById("languageStatusButton"); + let languageList = composeDocument.getElementById("languageMenuList"); + + shownPromise = BrowserTestUtils.waitForEvent(languageList, "popupshown"); + EventUtils.synthesizeMouseAtCenter(statusButton, {}, composeWindow); + await shownPromise; + + Assert.equal(languageList.childElementCount, 4); + Assert.equal(languageList.children[0].value, "en-NZ"); + Assert.equal(languageList.children[0].getAttribute("checked"), "false"); + Assert.equal(languageList.children[1].value, "en-US"); + Assert.equal(languageList.children[1].getAttribute("checked"), "true"); + Assert.equal(languageList.children[2].localName, "menuseparator"); + Assert.equal( + languageList.children[3].dataset.l10nId, + "spell-add-dictionaries" + ); + + hiddenPromise = BrowserTestUtils.waitForEvent(languageList, "popuphidden"); + languageList.activateItem(languageList.children[0]); + await TestUtils.waitForCondition( + () => languageList.children[0].getAttribute("checked") == "true", + "en-NZ menu item checked" + ); + await TestUtils.waitForCondition( + () => composeWindow.gActiveDictionaries.has("en-NZ"), + "en-NZ added to dictionaries" + ); + languageList.hidePopup(); + await hiddenPromise; + + Assert.deepEqual( + [...composeWindow.gActiveDictionaries], + ["en-US", "en-NZ"], + "correct dictionaries active" + ); + await checkMisspelledWords(subjectEditor); + await checkMisspelledWords(bodyEditor); + + // Remove language. + + shownPromise = BrowserTestUtils.waitForEvent(languageList, "popupshown"); + EventUtils.synthesizeMouseAtCenter(statusButton, {}, composeWindow); + await shownPromise; + + Assert.equal(languageList.childElementCount, 4); + Assert.equal(languageList.children[0].value, "en-NZ"); + Assert.equal(languageList.children[0].getAttribute("checked"), "true"); + Assert.equal(languageList.children[1].value, "en-US"); + Assert.equal(languageList.children[1].getAttribute("checked"), "true"); + Assert.equal(languageList.children[2].localName, "menuseparator"); + Assert.equal( + languageList.children[3].dataset.l10nId, + "spell-add-dictionaries" + ); + + hiddenPromise = BrowserTestUtils.waitForEvent(languageList, "popuphidden"); + languageList.activateItem(languageList.children[1]); + await TestUtils.waitForCondition( + () => !languageList.children[1].hasAttribute("checked"), + "en-US menu item unchecked" + ); + await TestUtils.waitForCondition( + () => !composeWindow.gActiveDictionaries.has("en-US"), + "en-US removed from dictionaries" + ); + languageList.hidePopup(); + await hiddenPromise; + + Assert.deepEqual( + [...composeWindow.gActiveDictionaries], + ["en-NZ"], + "correct dictionaries active" + ); + await checkMisspelledWords(subjectEditor, "harbor"); + let words = await checkMisspelledWords( + bodyEditor, + "maneuvered", + "center", + "jewelry" + ); + + // Check that opening the context menu on a spelling error works as expected. + + let box = words.getRangeAt(1).getBoundingClientRect(); + shownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + BrowserTestUtils.synthesizeMouseAtPoint( + box.left + box.width / 2, + box.top + box.height / 2, + { type: "contextmenu" }, + editorBrowser + ); + await shownPromise; + + let menuItem = composeDocument.getElementById("spellCheckNoSuggestions"); + Assert.ok(BrowserTestUtils.is_hidden(menuItem)); + + let suggestions = contextMenu.querySelectorAll(".spell-suggestion"); + Assert.greater(suggestions.length, 0); + Assert.equal(suggestions[0].value, "centre"); + + for (let id of [ + "spellCheckAddSep", + "spellCheckAddToDictionary", + "spellCheckIgnoreWord", + "spellCheckSuggestionsSeparator", + ]) { + menuItem = composeDocument.getElementById(id); + Assert.ok(BrowserTestUtils.is_visible(menuItem)); + } + + hiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden"); + contextMenu.activateItem(suggestions[0]); + await hiddenPromise; + + await checkMisspelledWords(bodyEditor, "maneuvered", "jewelry"); + await SpecialPowers.spawn(editorBrowser, [], () => { + Assert.ok( + content.document.body.textContent.startsWith( + "I maneuvered to the centre." + ) + ); + }); + + // Clean up. + + close_compose_window(cwc); + hunspell.removeDirectory(dictionary); +}); |