Add test coverage of DocDuplicator class

This commit is contained in:
Veronica Berglyd Olsen
2023-07-20 20:36:09 +02:00
parent 7a72634448
commit b3c744d22e
3 changed files with 248 additions and 5 deletions
+1
View File
@@ -292,6 +292,7 @@ class DocDuplicator:
hMap[tHandle] = newItem.itemHandle
if newItem.itemParent in hMap:
newItem.setParent(hMap[newItem.itemParent])
self._project.tree.updateItemData(newItem.itemHandle)
if newItem.isFileType():
oldDoc = self._project.storage.getDocument(tHandle)
newDoc = self._project.storage.getDocument(newItem.itemHandle)
@@ -0,0 +1,106 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.1-beta1" hexVersion="0x020100b1" fileVersion="1.5" fileRevision="1" timeStamp="2023-07-20 20:33:41">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="1" autoCount="1" editTime="0">
<name>New Project</name>
<title>New Novel</title>
<author>Jane Doe</author>
</project>
<settings>
<doBackup>yes</doBackup>
<language>None</language>
<spellChecking auto="no">None</spellChecking>
<lastHandle>
<entry key="editor">None</entry>
<entry key="viewer">None</entry>
<entry key="novelTree">None</entry>
<entry key="outline">None</entry>
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="15" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
</status>
<importance>
<entry key="i000004" count="3" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
</importance>
</settings>
<content items="18" novelWords="26" notesWords="0">
<item handle="0000000000008" parent="None" root="0000000000008" order="0" type="ROOT" class="NOVEL">
<meta expanded="no" />
<name status="s000000" import="i000004">Novel</name>
</item>
<item handle="0000000000009" parent="None" root="0000000000009" order="0" type="ROOT" class="PLOT">
<meta expanded="no" />
<name status="s000000" import="i000004">Plot</name>
</item>
<item handle="000000000000a" parent="None" root="000000000000a" order="0" type="ROOT" class="CHARACTER">
<meta expanded="no" />
<name status="s000000" import="i000004">Characters</name>
</item>
<item handle="000000000000b" parent="None" root="000000000000b" order="0" type="ROOT" class="WORLD">
<meta expanded="no" />
<name status="s000000" import="i000004">World</name>
</item>
<item handle="000000000000c" parent="0000000000008" root="0000000000008" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H1" charCount="20" wordCount="5" paraCount="1" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">Title Page</name>
</item>
<item handle="000000000000d" parent="0000000000008" root="0000000000008" order="0" type="FOLDER" class="NOVEL">
<meta expanded="no" />
<name status="s000000" import="i000004">New Chapter</name>
</item>
<item handle="000000000000e" parent="000000000000d" root="0000000000008" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H2" charCount="11" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Chapter</name>
</item>
<item handle="000000000000f" parent="000000000000d" root="0000000000008" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="9" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Scene</name>
</item>
<item handle="0000000000010" parent="000000000000d" root="0000000000008" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="9" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Scene</name>
</item>
<item handle="0000000000011" parent="0000000000008" root="0000000000008" order="0" type="FOLDER" class="NOVEL">
<meta expanded="no" />
<name status="s000000" import="i000004">New Chapter</name>
</item>
<item handle="0000000000012" parent="0000000000011" root="0000000000008" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H2" charCount="11" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Chapter</name>
</item>
<item handle="0000000000013" parent="0000000000011" root="0000000000008" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="9" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Scene</name>
</item>
<item handle="0000000000014" parent="None" root="0000000000008" order="0" type="ROOT" class="NOVEL">
<meta expanded="no" />
<name status="s000000" import="i000004">Novel</name>
</item>
<item handle="0000000000015" parent="0000000000014" root="0000000000014" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H1" charCount="20" wordCount="5" paraCount="1" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">Title Page</name>
</item>
<item handle="0000000000016" parent="0000000000014" root="0000000000014" order="0" type="FOLDER" class="NOVEL">
<meta expanded="no" />
<name status="s000000" import="i000004">New Chapter</name>
</item>
<item handle="0000000000017" parent="0000000000016" root="0000000000014" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H2" charCount="11" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Chapter</name>
</item>
<item handle="0000000000018" parent="0000000000016" root="0000000000014" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="9" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Scene</name>
</item>
<item handle="0000000000019" parent="000000000000d" root="0000000000008" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H2" charCount="11" wordCount="2" paraCount="0" cursorPos="0" />
<name status="s000000" import="i000004" active="yes">New Chapter</name>
</item>
</content>
</novelWriterXML>
+141 -5
View File
@@ -19,6 +19,7 @@ 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 pathlib import Path
import uuid
import pytest
@@ -31,13 +32,12 @@ from tools import C, buildTestProject, cmpFiles, XML_IGNORE
from novelwriter import CONFIG
from novelwriter.constants import nwItemClass
from novelwriter.core.project import NWProject
from novelwriter.core.coretools import DocMerger, DocSplitter, ProjectBuilder
from novelwriter.core.coretools import DocDuplicator, DocMerger, DocSplitter, ProjectBuilder
@pytest.mark.core
def testCoreTools_DocMerger(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd, ipsumText):
"""Test the DocMerger utility.
"""
"""Test the DocMerger utility."""
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncPath)
@@ -125,8 +125,7 @@ def testCoreTools_DocMerger(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd, ip
@pytest.mark.core
def testCoreTools_DocSplitter(monkeypatch, mockGUI, fncPath, mockRnd, ipsumText):
"""Test the DocSplitter utility.
"""
"""Test the DocSplitter utility."""
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncPath)
@@ -263,6 +262,143 @@ def testCoreTools_DocSplitter(monkeypatch, mockGUI, fncPath, mockRnd, ipsumText)
# END Test testCoreTools_DocSplitter
@pytest.mark.core
def testCoreTools_DocDuplicator(mockGUI, fncPath, tstPaths, mockRnd):
"""Test the DocDuplicator utility."""
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncPath)
dup = DocDuplicator(theProject)
ttText = "#! New Novel\n\n>> By Jane Doe <<\n"
chText = "## New Chapter\n\n"
scText = "### New Scene\n\n"
# Check document content
assert theProject.storage.getDocument(C.hTitlePage).readDocument() == ttText
assert theProject.storage.getDocument(C.hChapterDoc).readDocument() == chText
assert theProject.storage.getDocument(C.hSceneDoc).readDocument() == scText
# Nothing to do
assert list(dup.duplicate([])) == []
# Single Document
# ===============
# A new copy is created
assert list(dup.duplicate([C.hSceneDoc])) == [
("0000000000010", C.hSceneDoc), # The Scene
]
assert theProject.tree._treeOrder == [
C.hNovelRoot, C.hPlotRoot, C.hCharRoot, C.hWorldRoot,
C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010",
]
# With the same content
assert theProject.storage.getDocument("0000000000010").readDocument() == scText
# They should have the same parent
assert theProject.tree["0000000000010"].itemParent == C.hChapterDir # type: ignore
# Folder w/Two Files
# ==================
# The folder is copied, with two docs
assert list(dup.duplicate([C.hChapterDir, C.hChapterDoc, C.hSceneDoc])) == [
("0000000000011", C.hChapterDir), # The Folder
("0000000000012", None), # The Chapter
("0000000000013", None), # The Scene
]
assert theProject.tree._treeOrder == [
C.hNovelRoot, C.hPlotRoot, C.hCharRoot, C.hWorldRoot,
C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010",
"0000000000011", "0000000000012", "0000000000013",
]
# With the same content
assert theProject.storage.getDocument("0000000000012").readDocument() == chText
assert theProject.storage.getDocument("0000000000013").readDocument() == scText
# The chapter dirs should have the same parent
assert theProject.tree["0000000000011"].itemParent == C.hNovelRoot # type: ignore
# The new files should have the new folder as parent
assert theProject.tree["0000000000012"].itemParent == "0000000000011" # type: ignore
assert theProject.tree["0000000000013"].itemParent == "0000000000011" # type: ignore
# Full Root Folder
# ================
# The root is copied, with three docs and a folder
assert list(dup.duplicate(
[C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc]
)) == [
("0000000000014", C.hNovelRoot), # The Root
("0000000000015", None), # The Title Page
("0000000000016", None), # The Folder
("0000000000017", None), # The Chapter
("0000000000018", None), # The Scene
]
assert theProject.tree._treeOrder == [
C.hNovelRoot, C.hPlotRoot, C.hCharRoot, C.hWorldRoot,
C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
"0000000000010",
"0000000000011", "0000000000012", "0000000000013",
"0000000000014", "0000000000015", "0000000000016", "0000000000017", "0000000000018",
]
# With the same content
assert theProject.storage.getDocument("0000000000015").readDocument() == ttText
assert theProject.storage.getDocument("0000000000017").readDocument() == chText
assert theProject.storage.getDocument("0000000000018").readDocument() == scText
# The root folder should have no parent
assert theProject.tree["0000000000014"].itemParent is None # type: ignore
# The folder and files should have the new root
assert theProject.tree["0000000000015"].itemRoot == "0000000000014" # type: ignore
assert theProject.tree["0000000000016"].itemRoot == "0000000000014" # type: ignore
assert theProject.tree["0000000000017"].itemRoot == "0000000000014" # type: ignore
assert theProject.tree["0000000000018"].itemRoot == "0000000000014" # type: ignore
# And they should have new parents
assert theProject.tree["0000000000015"].itemParent == "0000000000014" # type: ignore
assert theProject.tree["0000000000016"].itemParent == "0000000000014" # type: ignore
assert theProject.tree["0000000000017"].itemParent == "0000000000016" # type: ignore
assert theProject.tree["0000000000018"].itemParent == "0000000000016" # type: ignore
# Exceptions
# ==========
# Handle invalid items
assert list(dup.duplicate([C.hInvalid])) == []
# Also stop early if invalid items are encountered
assert list(dup.duplicate([C.hInvalid, C.hSceneDoc])) == []
# Don't overwrite existing files
content = theProject.storage.contentPath
assert isinstance(content, Path)
(content / "0000000000019.nwd").touch()
assert (content / "0000000000019.nwd").exists()
assert list(dup.duplicate([C.hChapterDoc, C.hSceneDoc])) == []
# Save and Close
theProject.saveProject()
projFile = fncPath / "nwProject.nwx"
testFile = tstPaths.outDir / "coreTools_DocDuplicator_nwProject.nwx"
compFile = tstPaths.refDir / "coreTools_DocDuplicator_nwProject.nwx"
copyfile(projFile, testFile)
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
# END Test testCoreTools_DocDuplicator
@pytest.mark.core
def testCoreTools_NewMinimal(monkeypatch, fncPath, tstPaths, mockGUI, mockRnd):
"""Create a new project from a project wizard dictionary. With