Move spell check testing to the editor

This commit is contained in:
Veronica Berglyd Olsen
2025-03-30 23:49:19 +02:00
parent 01275876c1
commit d0c8227d15
5 changed files with 45 additions and 34 deletions
+1 -1
View File
@@ -473,7 +473,7 @@ class TextBlockData(QTextBlockUserData):
self._text = "" self._text = ""
self._offset = 0 self._offset = 0
self._metaData: list[tuple[int, int, str, str]] = [] self._metaData: list[tuple[int, int, str, str]] = []
self._spellErrors: list[tuple[int, int,]] = [] self._spellErrors: list[tuple[int, int]] = []
return return
@property @property
@@ -1,8 +1,8 @@
%%~name: New Scene %%~name: New Scene
%%~path: 000000000000d/000000000000f %%~path: 000000000000d/000000000000f
%%~kind: NOVEL/DOCUMENT %%~kind: NOVEL/DOCUMENT
%%~hash: e4148ea77e78c90c334d5dc46c38a2b7904ac117 %%~hash: e3cdc10e73d6250cc4eb9c24fcc4fed1e72392ff
%%~date: 2024-11-01 21:15:57/2024-11-01 21:16:01 %%~date: 2025-03-30 23:25:06/2025-03-30 23:25:11
# Novel # Novel
## Chapter ## Chapter
@@ -60,5 +60,3 @@ But dont add a double space : See?
>>Right-aligned text >>Right-aligned text
Some text with tesst in it.
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.6b1" hexVersion="0x020600b1" fileVersion="1.5" fileRevision="4" timeStamp="2024-11-23 23:35:44"> <novelWriterXML appVersion="2.7a3" hexVersion="0x020700a3" fileVersion="1.5" fileRevision="4" timeStamp="2025-03-30 23:23:22">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="3" autoCount="2" editTime="4"> <project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="3" autoCount="2" editTime="5">
<name>New Project</name> <name>New Project</name>
<author>Jane Doe</author> <author>Jane Doe</author>
</project> </project>
@@ -28,7 +28,7 @@
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry> <entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance> </importance>
</settings> </settings>
<content items="12" novelWords="179" notesWords="27"> <content items="12" novelWords="173" notesWords="27">
<item handle="0000000000008" parent="None" root="0000000000008" order="0" type="ROOT" class="NOVEL"> <item handle="0000000000008" parent="None" root="0000000000008" order="0" type="ROOT" class="NOVEL">
<meta expanded="yes" /> <meta expanded="yes" />
<name status="s000000" import="i000004">Novel</name> <name status="s000000" import="i000004">Novel</name>
@@ -46,7 +46,7 @@
<name status="s000000" import="i000004" active="yes">New Chapter</name> <name status="s000000" import="i000004" active="yes">New Chapter</name>
</item> </item>
<item handle="000000000000f" parent="000000000000d" root="0000000000008" order="1" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="000000000000f" parent="000000000000d" root="0000000000008" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H1" charCount="1003" wordCount="172" paraCount="17" cursorPos="1259" /> <meta expanded="no" heading="H1" charCount="976" wordCount="166" paraCount="16" cursorPos="1243" />
<name status="s000000" import="i000004" active="yes">New Scene</name> <name status="s000000" import="i000004" active="yes">New Scene</name>
</item> </item>
<item handle="0000000000009" parent="None" root="0000000000009" order="1" type="ROOT" class="PLOT"> <item handle="0000000000009" parent="None" root="0000000000009" order="1" type="ROOT" class="PLOT">
+18 -4
View File
@@ -37,6 +37,7 @@ from novelwriter.constants import nwKeyWords, nwUnicode
from novelwriter.dialogs.editlabel import GuiEditLabel from novelwriter.dialogs.editlabel import GuiEditLabel
from novelwriter.enum import nwDocAction, nwDocInsert, nwItemClass, nwItemLayout from novelwriter.enum import nwDocAction, nwDocInsert, nwItemClass, nwItemLayout
from novelwriter.gui.doceditor import GuiDocEditor, _TagAction from novelwriter.gui.doceditor import GuiDocEditor, _TagAction
from novelwriter.gui.dochighlight import TextBlockData
from novelwriter.text.counting import standardCounter from novelwriter.text.counting import standardCounter
from novelwriter.types import ( from novelwriter.types import (
QtAlignJustify, QtAlignLeft, QtKeepAnchor, QtModCtrl, QtModNone, QtAlignJustify, QtAlignLeft, QtKeepAnchor, QtModCtrl, QtModNone,
@@ -58,7 +59,7 @@ def getMenuForPos(editor: GuiDocEditor, pos: int, select: bool = False) -> QMenu
if select: if select:
cursor.select(QTextCursor.SelectionType.WordUnderCursor) cursor.select(QTextCursor.SelectionType.WordUnderCursor)
editor.setTextCursor(cursor) editor.setTextCursor(cursor)
editor._openContextMenu(editor.cursorRect().center()) editor._openContextFromCursor()
for obj in editor.children(): for obj in editor.children():
if isinstance(obj, QMenu) and obj.objectName() == "ContextMenu": if isinstance(obj, QMenu) and obj.objectName() == "ContextMenu":
return obj return obj
@@ -514,9 +515,20 @@ def testGuiEditor_SpellChecking(qtbot, monkeypatch, nwGUI, projPath, ipsumText,
# ============== # ==============
SHARED.project.data.setSpellCheck(True) SHARED.project.data.setSpellCheck(True)
cursor = docEditor.textCursor()
cursor.setPosition(16)
data = cursor.block().userData()
assert cursor.block().text().startswith("Lorem")
assert isinstance(data, TextBlockData)
data._spellErrors = [(0, 5)]
# No known position
assert docEditor._qDocument.spellErrorAtPos(-1) == ("", -1, -1, [])
# With Suggestion # With Suggestion
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(docEditor._qDocument, "spellErrorAtPos", lambda *a: ("Lorem", 0, 5, ["Lorax"])) mp.setattr(SHARED.spelling, "suggestWords", lambda *a: ["Lorax"])
ctxMenu = getMenuForPos(docEditor, 16) ctxMenu = getMenuForPos(docEditor, 16)
assert ctxMenu is not None assert ctxMenu is not None
actions = [x.text() for x in ctxMenu.actions() if x.text()] actions = [x.text() for x in ctxMenu.actions() if x.text()]
@@ -530,7 +542,8 @@ def testGuiEditor_SpellChecking(qtbot, monkeypatch, nwGUI, projPath, ipsumText,
# Without Suggestion # Without Suggestion
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(docEditor._qDocument, "spellErrorAtPos", lambda *a: ("Lorax", 0, 5, [])) mp.setattr(SHARED.spelling, "suggestWords", lambda *a: [])
ctxMenu = getMenuForPos(docEditor, 16) ctxMenu = getMenuForPos(docEditor, 16)
assert ctxMenu is not None assert ctxMenu is not None
actions = [x.text() for x in ctxMenu.actions() if x.text()] actions = [x.text() for x in ctxMenu.actions() if x.text()]
@@ -541,7 +554,8 @@ def testGuiEditor_SpellChecking(qtbot, monkeypatch, nwGUI, projPath, ipsumText,
# Add to Dictionary # Add to Dictionary
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(docEditor._qDocument, "spellErrorAtPos", lambda *a: ("Lorax", 0, 5, [])) mp.setattr(SHARED.spelling, "suggestWords", lambda *a: [])
ctxMenu = getMenuForPos(docEditor, 16) ctxMenu = getMenuForPos(docEditor, 16)
assert ctxMenu is not None assert ctxMenu is not None
actions = [x.text() for x in ctxMenu.actions() if x.text()] actions = [x.text() for x in ctxMenu.actions() if x.text()]
+20 -21
View File
@@ -21,7 +21,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
from __future__ import annotations from __future__ import annotations
import shutil import shutil
import sys
from pathlib import Path from pathlib import Path
from shutil import copyfile from shutil import copyfile
@@ -30,7 +29,7 @@ import pytest
from PyQt6.QtCore import Qt from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPalette from PyQt6.QtGui import QPalette
from PyQt6.QtWidgets import QInputDialog, QMenu, QMessageBox from PyQt6.QtWidgets import QInputDialog, QMessageBox
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.constants import nwFiles from novelwriter.constants import nwFiles
@@ -569,28 +568,28 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
# Spell Checking # Spell Checking
# ============== # ==============
for c in "Some text with tesst in it.": # for c in "Some text with tesst in it.":
qtbot.keyClick(docEditor, c, delay=KEY_DELAY) # qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY) # qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY) # qtbot.keyClick(docEditor, Qt.Key.Key_Return, delay=KEY_DELAY)
currPos = docEditor.getCursorPosition() # currPos = docEditor.getCursorPosition()
assert docEditor._qDocument.spellErrorAtPos(currPos) == ("", -1, -1, []) # assert docEditor._qDocument.spellErrorAtPos(currPos) == ("", -1, -1, [])
errPos = currPos - 13 # errPos = currPos - 13
if not sys.platform.startswith("win32"): # if not sys.platform.startswith("win32"):
# Skip on Windows as spell checking is off there # # Skip on Windows as spell checking is off there
# This check will fail without an 'en' dictionary, like aspell-en # # This check will fail without an 'en' dictionary, like aspell-en
word, cPos, cLen, suggest = docEditor._qDocument.spellErrorAtPos(errPos) # word, cPos, cLen, suggest = docEditor._qDocument.spellErrorAtPos(errPos)
assert word == "tesst" # assert word == "tesst"
assert cPos == 15 # assert cPos == 15
assert cLen == 5 # assert cLen == 5
assert "test" in suggest # assert "test" in suggest
with monkeypatch.context() as mp: # with monkeypatch.context() as mp:
mp.setattr(QMenu, "exec", lambda *a: None) # mp.setattr(QMenu, "exec", lambda *a: None)
docEditor.setCursorPosition(errPos) # docEditor.setCursorPosition(errPos)
docEditor._openContextFromCursor() # docEditor._openContextFromCursor()
# Check Files # Check Files
# =========== # ===========