Add novel model test coverage
This commit is contained in:
@@ -22,6 +22,7 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.core.index import TagsIndex
|
||||
from novelwriter.core.indexdata import IndexHeading, IndexNode
|
||||
from novelwriter.core.item import NWItem
|
||||
@@ -179,6 +180,7 @@ def testCoreIndexData_IndexHeading():
|
||||
assert head.charCount == 0
|
||||
assert head.wordCount == 0
|
||||
assert head.paraCount == 0
|
||||
assert head.mainCount == 0
|
||||
assert head.synopsis == ""
|
||||
assert head.tag == ""
|
||||
assert head.references == {}
|
||||
@@ -205,6 +207,11 @@ def testCoreIndexData_IndexHeading():
|
||||
assert head.wordCount == 4
|
||||
assert head.paraCount == 2
|
||||
|
||||
# Check Main Count
|
||||
assert head.mainCount == 4
|
||||
CONFIG.useCharCount = True
|
||||
assert head.mainCount == 42
|
||||
|
||||
# Set Summary
|
||||
head.setSynopsis("In the beginning ...")
|
||||
assert head.synopsis == "In the beginning ..."
|
||||
@@ -235,6 +242,72 @@ def testCoreIndexData_IndexHeading():
|
||||
assert head.synopsis == "How it started ..."
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndexData_IndexHeadingReferences():
|
||||
"""Test the IndexHeading references handling."""
|
||||
tags = TagsIndex()
|
||||
head = IndexHeading(tags, "T0001")
|
||||
|
||||
# Add some references
|
||||
head.addReference("Jane", "@pov")
|
||||
head.addReference("Jane", "@char")
|
||||
head.addReference("John", "@char")
|
||||
head.addReference("Main", "@plot")
|
||||
head.addReference("Gun", "@object")
|
||||
|
||||
# With no tagsIndex name set, these should be empty
|
||||
assert head.getReferences() == {
|
||||
"@entity": [],
|
||||
"@plot": [],
|
||||
"@object": [],
|
||||
"@story": [],
|
||||
"@tag": [],
|
||||
"@focus": [],
|
||||
"@custom": [],
|
||||
"@time": [],
|
||||
"@pov": [],
|
||||
"@mention": [],
|
||||
"@char": [],
|
||||
"@location": [],
|
||||
}
|
||||
|
||||
# Set names
|
||||
tags.add("Jane", "Jane", "0000000000000", "T00001", "CHARACTER")
|
||||
tags.add("John", "John", "0000000000000", "T00001", "CHARACTER")
|
||||
tags.add("Main", "Main", "0000000000000", "T00001", "PLOT")
|
||||
tags.add("Gun", "Gun", "0000000000000", "T00001", "OBJECT")
|
||||
|
||||
# Now they should be populated
|
||||
assert head.getReferences() == {
|
||||
"@entity": [],
|
||||
"@plot": ["Main"],
|
||||
"@object": ["Gun"],
|
||||
"@story": [],
|
||||
"@tag": [],
|
||||
"@focus": [],
|
||||
"@custom": [],
|
||||
"@time": [],
|
||||
"@pov": ["Jane"],
|
||||
"@mention": [],
|
||||
"@char": ["Jane", "John"],
|
||||
"@location": [],
|
||||
}
|
||||
|
||||
# Check them individually
|
||||
assert head.getReferencesByKeyword("@entity") == []
|
||||
assert head.getReferencesByKeyword("@plot") == ["Main"]
|
||||
assert head.getReferencesByKeyword("@object") == ["Gun"]
|
||||
assert head.getReferencesByKeyword("@story") == []
|
||||
assert head.getReferencesByKeyword("@tag") == []
|
||||
assert head.getReferencesByKeyword("@focus") == []
|
||||
assert head.getReferencesByKeyword("@custom") == []
|
||||
assert head.getReferencesByKeyword("@time") == []
|
||||
assert head.getReferencesByKeyword("@pov") == ["Jane"]
|
||||
assert head.getReferencesByKeyword("@mention") == []
|
||||
assert head.getReferencesByKeyword("@char") == ["Jane", "John"]
|
||||
assert head.getReferencesByKeyword("@location") == []
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndexData_IndexHeadingUnpackMeta():
|
||||
"""Test IndexHeading class meta unpacking."""
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
"""
|
||||
novelWriter – Novel Model Tester
|
||||
================================
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright (C) 2025 Veronica Berglyd Olsen and novelWriter contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt6.QtCore import QModelIndex, Qt
|
||||
|
||||
from novelwriter.core.indexdata import IndexHeading
|
||||
from novelwriter.core.novelmodel import NovelModel
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.enum import nwNovelExtra
|
||||
|
||||
from tests.tools import C, buildTestProject
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreNovelModel_Interface(nwGUI, fncPath, mockRnd):
|
||||
"""Test the novel model interface."""
|
||||
project = NWProject()
|
||||
mockRnd.reset()
|
||||
buildTestProject(project, fncPath)
|
||||
|
||||
model = project.index.getNovelModel(C.hNovelRoot)
|
||||
assert isinstance(model, NovelModel)
|
||||
|
||||
root = QModelIndex()
|
||||
assert root.row() == -1
|
||||
|
||||
# Initial structure
|
||||
assert model.rowCount(root) == 3
|
||||
assert model.columnCount(root) == 3
|
||||
assert model.data(model.createIndex(0, 0), Qt.ItemDataRole.DisplayRole) == "New Novel"
|
||||
assert model.handle(model.createIndex(0, 0)) == C.hTitlePage
|
||||
assert model.key(model.createIndex(0, 0)) == "T0001"
|
||||
|
||||
# Clear the model and check error handling
|
||||
model.clear()
|
||||
|
||||
assert model.data(root, Qt.ItemDataRole.DisplayRole) is None
|
||||
assert model.handle(root) is None
|
||||
assert model.key(root) is None
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreNovelModel_Extra(nwGUI, fncPath, mockRnd):
|
||||
"""Test the novel model extra column."""
|
||||
project = NWProject()
|
||||
mockRnd.reset()
|
||||
buildTestProject(project, fncPath)
|
||||
|
||||
root = QModelIndex()
|
||||
model = project.index.getNovelModel(C.hNovelRoot)
|
||||
assert isinstance(model, NovelModel)
|
||||
assert model.rowCount(root) == 3
|
||||
|
||||
project.index._tagsIndex.add("Jane", "Jane", "0000000000000", "T0001", "CHARACTER")
|
||||
project.index._tagsIndex.add("John", "John", "0000000000000", "T0001", "CHARACTER")
|
||||
project.index._tagsIndex.add("Main", "Main", "0000000000000", "T0001", "PLOT")
|
||||
project.index._tagsIndex.add("Side", "Side", "0000000000000", "T0001", "PLOT")
|
||||
|
||||
scene = project.index._itemIndex[C.hSceneDoc]
|
||||
assert scene is not None
|
||||
scene.addHeadingRef("T0001", ["Jane"], "@pov")
|
||||
scene.addHeadingRef("T0001", ["John"], "@focus")
|
||||
scene.addHeadingRef("T0001", ["Main"], "@plot")
|
||||
scene.addHeadingRef("T0001", ["Side"], "@plot")
|
||||
|
||||
# No extra by default
|
||||
assert model.columns == 3
|
||||
assert model._extraKey == ""
|
||||
assert model._extraLabel == ""
|
||||
|
||||
# Point of view
|
||||
model.setExtraColumn(nwNovelExtra.POV)
|
||||
model.refresh(scene)
|
||||
assert model.columns == 4
|
||||
assert model._extraKey == "@pov"
|
||||
assert model._extraLabel == "Point of View"
|
||||
assert model.data(model.createIndex(2, 2), Qt.ItemDataRole.DisplayRole) == "Jane"
|
||||
|
||||
model.setExtraColumn(nwNovelExtra.HIDDEN)
|
||||
assert model.columns == 3
|
||||
|
||||
# Focus
|
||||
model.setExtraColumn(nwNovelExtra.FOCUS)
|
||||
model.refresh(scene)
|
||||
assert model.columns == 4
|
||||
assert model._extraKey == "@focus"
|
||||
assert model._extraLabel == "Focus"
|
||||
assert model.data(model.createIndex(2, 2), Qt.ItemDataRole.DisplayRole) == "John"
|
||||
|
||||
model.setExtraColumn(nwNovelExtra.HIDDEN)
|
||||
assert model.columns == 3
|
||||
|
||||
# Plot
|
||||
model.setExtraColumn(nwNovelExtra.PLOT)
|
||||
model.refresh(scene)
|
||||
assert model.columns == 4
|
||||
assert model._extraKey == "@plot"
|
||||
assert model._extraLabel == "Plot"
|
||||
assert model.data(model.createIndex(2, 2), Qt.ItemDataRole.DisplayRole) == "Main, Side"
|
||||
|
||||
model.setExtraColumn(nwNovelExtra.HIDDEN)
|
||||
assert model.columns == 3
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreNovelModel_Data(nwGUI, fncPath, mockRnd):
|
||||
"""Test the novel model data methods."""
|
||||
project = NWProject()
|
||||
mockRnd.reset()
|
||||
buildTestProject(project, fncPath)
|
||||
|
||||
root = QModelIndex()
|
||||
model = project.index.getNovelModel(C.hNovelRoot)
|
||||
assert isinstance(model, NovelModel)
|
||||
assert model.rowCount(root) == 3
|
||||
|
||||
title = project.index._itemIndex[C.hTitlePage]
|
||||
chapter = project.index._itemIndex[C.hChapterDoc]
|
||||
scene = project.index._itemIndex[C.hSceneDoc]
|
||||
|
||||
assert title is not None
|
||||
assert chapter is not None
|
||||
assert scene is not None
|
||||
|
||||
# Clear the model and try to refresh
|
||||
model.clear()
|
||||
assert model.rowCount(root) == 0
|
||||
|
||||
# Cannot refresh an empty model
|
||||
assert model.refresh(title) is False
|
||||
|
||||
# Add all back
|
||||
model.append(title)
|
||||
model.append(chapter)
|
||||
model.append(scene)
|
||||
|
||||
# Add headings to scene
|
||||
scene.addHeading(IndexHeading(scene._tags, "T0002", 10, "H4", "A Section"))
|
||||
scene.addHeading(IndexHeading(scene._tags, "T0003", 10, "H4", "Another Section"))
|
||||
assert model.refresh(scene) is True
|
||||
assert [
|
||||
model.data(model.createIndex(i, 0), Qt.ItemDataRole.DisplayRole)
|
||||
for i in range(model.rowCount(root))
|
||||
] == [
|
||||
"New Novel", "New Chapter", "New Scene", "A Section", "Another Section",
|
||||
]
|
||||
|
||||
# Remove new headings
|
||||
del scene._headings["T0002"]
|
||||
del scene._headings["T0003"]
|
||||
assert model.refresh(scene) is True
|
||||
assert [
|
||||
model.data(model.createIndex(i, 0), Qt.ItemDataRole.DisplayRole)
|
||||
for i in range(model.rowCount(root))
|
||||
] == [
|
||||
"New Novel", "New Chapter", "New Scene",
|
||||
]
|
||||
Reference in New Issue
Block a user