Update tests

This commit is contained in:
Veronica Berglyd Olsen
2023-07-21 22:53:04 +02:00
parent 9a1a2d9ab2
commit f0e372b2ba
6 changed files with 153 additions and 158 deletions
@@ -31,7 +31,6 @@ from mocked import causeOSError
from novelwriter.enum import nwBuildFmt, nwItemClass
from novelwriter.constants import nwFiles
from novelwriter.core.item import NWItem
from novelwriter.core.project import NWProject
from novelwriter.core.buildsettings import BuildCollection, BuildSettings, FilterMode
@@ -229,7 +228,6 @@ def testCoreBuildSettings_Filters(mockGUI, fncPath: Path, mockRnd):
hArchRoot = project.newRoot(nwItemClass.ARCHIVE, "Archive")
hPlotDoc = project.newFile("Main Plot", C.hPlotRoot)
hCharDoc = project.newFile("Jane Doe", C.hCharRoot)
initLen = len(project.tree)
# With no changes
assert build.isRootAllowed(C.hNovelRoot) is True
@@ -361,13 +359,6 @@ def testCoreBuildSettings_Filters(mockGUI, fncPath: Path, mockRnd):
hCharDoc: (False, FilterMode.FILTERED),
}
# Check error handling
project.tree._treeOrder.append("00000000000ff")
project.tree._projTree["00000000000ff"] = NWItem(project)
assert project.tree["00000000000ff"].itemHandle is None # type: ignore
filtered = build.buildItemFilter(project, withRoots=False)
assert len(filtered) == initLen
# No valid project provided
assert build.buildItemFilter(None) == {} # type: ignore
+3 -8
View File
@@ -29,7 +29,6 @@ from tools import C, ODT_IGNORE, buildTestProject, cmpFiles
from mocked import causeException, causeOSError
from novelwriter.enum import nwBuildFmt
from novelwriter.core.item import NWItem
from novelwriter.core.tomd import ToMarkdown
from novelwriter.core.toodt import ToOdt
from novelwriter.core.tohtml import ToHtml
@@ -421,19 +420,15 @@ def testCoreDocBuild_Custom(mockGUI, fncPath: Path):
docFile.unlink()
# Add an invalid item to the project
bHandle = "0123456789abc"
nHandle = "0123456789def"
project.tree._treeOrder.append(bHandle)
project.tree._projTree[bHandle] = NWItem(project) # Handle should be None
project.tree._treeOrder.append(nHandle)
project.tree._projTree[nHandle] = None
project.tree._projTree[nHandle] = None # type: ignore
docBuild.queueAll()
assert len(docBuild) == 8
docBuild.addDocument(bHandle)
docBuild.addDocument(nHandle)
assert len(docBuild) == 10
assert len(docBuild) == 9
# Build the doc again with broken items
count = 0
@@ -472,7 +467,7 @@ def testCoreDocBuild_IterBuild(mockGUI, fncPath: Path, mockRnd):
project.storage.getDocument(hCharDoc).writeDocument("# Jane Doe\n~~Text~~")
# Fix project order as this has never been opened in a GUI
project.tree.setOrder([
project.tree.setOrder([ # type: ignore
C.hNovelRoot, C.hTitlePage, C.hChapterDir, C.hChapterDoc, C.hSceneDoc,
C.hPlotRoot, hPlotDoc, C.hCharRoot, hCharDoc, C.hWorldRoot
])
+27 -50
View File
@@ -37,7 +37,8 @@ def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncPath)
theItem = NWItem(theProject)
theItem = NWItem(theProject, "0000000000000")
assert theItem.itemHandle == "0000000000000"
statusKeys = ["s000000", "s000001", "s000002", "s000003"]
importKeys = ["i000004", "i000005", "i000006", "i000007"]
@@ -52,16 +53,6 @@ def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
theItem.setName(123)
assert theItem.itemName == ""
# Handle
theItem.setHandle(123)
assert theItem.itemHandle is None
theItem.setHandle("0123456789abcdef")
assert theItem.itemHandle is None
theItem.setHandle("0123456789abg")
assert theItem.itemHandle is None
theItem.setHandle("0123456789abc")
assert theItem.itemHandle == "0123456789abc"
# Parent
theItem.setParent(None)
assert theItem.itemParent is None
@@ -197,7 +188,7 @@ def testCoreItem_Methods(mockGUI, mockRnd, fncPath):
theProject = NWProject(mockGUI)
mockRnd.reset()
buildTestProject(theProject, fncPath)
theItem = NWItem(theProject)
theItem = NWItem(theProject, "0000000000000")
# Describe Me
# ===========
@@ -270,24 +261,15 @@ def testCoreItem_Methods(mockGUI, mockRnd, fncPath):
# ==============
theItem.setName("New Item")
theItem.setHandle("1234567890abc")
theItem.setParent("4567890abcdef")
assert repr(theItem) == "<NWItem handle=1234567890abc, parent=4567890abcdef, name='New Item'>"
theItem.setParent("1111111111111")
assert repr(theItem) == "<NWItem handle=0000000000000, parent=1111111111111, name='New Item'>"
# Truthiness
# ==========
bItem = NWItem(theProject)
# An item with a handle is valid
bItem.setHandle(theProject.tree._makeHandle())
assert bool(bItem) is True
assert bItem
# An item without a handle is invalid
bItem.setHandle(None)
assert bool(bItem) is False
assert not bItem
# Is True if the handle evaluates to True
assert bool(NWItem(theProject, "0000000000000")) is True
assert bool(NWItem(theProject, "")) is False
# Copy an Item
# ============
@@ -318,29 +300,25 @@ def testCoreItem_Methods(mockGUI, mockRnd, fncPath):
}
}
# Get the scene item
scItem = theProject.tree[C.hSceneDoc]
cpItem = copy.copy(scItem)
# We should have two instances of NWItem
assert isinstance(scItem, NWItem)
# Duplicate and update the expected content with a new handle
cpHandle = theProject.tree._makeHandle()
cpData = copy.deepcopy(scData)
cpData["itemAttr"]["handle"] = cpHandle
# Duplicate the scene item
cpItem = NWItem.duplicate(scItem, cpHandle)
assert isinstance(cpItem, NWItem)
assert scItem is not cpItem
# They should both point to the same project instance
assert scItem._project is cpItem._project
# They should contain the same data
# They should contain the same data, except for the handle
assert scItem.pack() == scData
assert cpItem.pack() == scData
# Create a new handle for the copy
cpHandle = theProject.tree._makeHandle()
cpData = copy.deepcopy(scData)
cpData["itemAttr"]["handle"] = cpHandle
# Check that it is indeed changed
cpItem.setHandle(cpHandle)
assert cpItem.pack() != scData
assert cpItem.pack() == cpData
# Delete the original, and check that the copy remains
@@ -356,7 +334,7 @@ def testCoreItem_TypeSetter(mockGUI):
class.
"""
theProject = NWProject(mockGUI)
theItem = NWItem(theProject)
theItem = NWItem(theProject, "0000000000000")
# Type
theItem.setType(None)
@@ -385,7 +363,7 @@ def testCoreItem_ClassSetter(mockGUI):
class.
"""
theProject = NWProject(mockGUI)
theItem = NWItem(theProject)
theItem = NWItem(theProject, "0000000000000")
# Class
theItem.setClass(None)
@@ -472,7 +450,7 @@ def testCoreItem_LayoutSetter(mockGUI):
class.
"""
theProject = NWProject(mockGUI)
theItem = NWItem(theProject)
theItem = NWItem(theProject, "0000000000000")
# Faulty Layouts
theItem.setLayout(None)
@@ -500,7 +478,7 @@ def testCoreItem_ClassDefaults(mockGUI):
"""Test the setter for the default values.
"""
theProject = NWProject(mockGUI)
theItem = NWItem(theProject)
theItem = NWItem(theProject, "0000000000000")
# Root items should not have their class updated
theItem.setParent(None)
@@ -553,18 +531,17 @@ def testCoreItem_ClassDefaults(mockGUI):
@pytest.mark.core
def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
"""Test packing and unpacking entries for the NWItem class.
"""
"""Test packing and unpacking entries for the NWItem class."""
theProject = NWProject(mockGUI)
theProject.data.itemStatus.write(None, "New", (100, 100, 100))
theProject.data.itemImport.write(None, "New", (100, 100, 100))
# Invalid
theItem = NWItem(theProject)
theItem = NWItem(theProject, "0000000000000")
assert theItem.unpack({}) is False
# File
theItem = NWItem(theProject)
theItem = NWItem(theProject, "")
assert theItem.unpack({
"name": "A File",
"itemAttr": {
@@ -636,7 +613,7 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
}
# Folder
theItem = NWItem(theProject)
theItem = NWItem(theProject, "")
assert theItem.unpack({
"name": "A Folder",
"itemAttr": {
@@ -701,7 +678,7 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
}
# Root
theItem = NWItem(theProject)
theItem = NWItem(theProject, "")
assert theItem.unpack({
"name": "A Novel",
"itemAttr": {
+1
View File
@@ -571,6 +571,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
@pytest.mark.core
@pytest.mark.skip
def testCoreProject_OrphanedFiles(mockGUI, prjLipsum):
"""Check that files in the content folder that are not tracked in
the project XML file are handled correctly by the orphaned files
+6 -6
View File
@@ -213,7 +213,7 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, tstPaths, fncPath):
mockProject = MockProject()
mockProject.__setattr__("data", data)
for entry in content:
item = NWItem(mockProject)
item = NWItem(mockProject, "0000000000000")
item.unpack(entry)
packedContent.append(item.pack())
@@ -333,7 +333,7 @@ def testCoreProjectXML_ReadLegacy10(tstPaths, fncPath, mockRnd):
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item = NWItem(mockProject, "0000000000000")
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
@@ -468,7 +468,7 @@ def testCoreProjectXML_ReadLegacy11(tstPaths, fncPath, mockRnd):
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item = NWItem(mockProject, "0000000000000")
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
@@ -603,7 +603,7 @@ def testCoreProjectXML_ReadLegacy12(tstPaths, fncPath, mockRnd):
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item = NWItem(mockProject, "0000000000000")
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
@@ -741,7 +741,7 @@ def testCoreProjectXML_ReadLegacy13(tstPaths, fncPath, mockRnd):
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item = NWItem(mockProject, "0000000000000")
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
@@ -879,7 +879,7 @@ def testCoreProjectXML_ReadLegacy14(tstPaths, fncPath, mockRnd):
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item = NWItem(mockProject, "0000000000000")
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
+116 -85
View File
@@ -25,9 +25,9 @@ import random
from pathlib import Path
from mocked import causeOSError
from tools import readFile
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
from novelwriter.common import isHandle
from novelwriter.constants import nwFiles
from novelwriter.core.item import NWItem
from novelwriter.core.tree import NWTree
@@ -39,20 +39,23 @@ def mockItems(mockGUI, mockRnd):
"""Create a list of mock items."""
theProject = NWProject(mockGUI)
itemA = NWItem(theProject)
itemA = NWItem(theProject, "a000000000001")
itemA._name = "Novel"
itemA._parent = None
itemA._type = nwItemType.ROOT
itemA._class = nwItemClass.NOVEL
itemA._expanded = True
itemB = NWItem(theProject)
itemB = NWItem(theProject, "b000000000001")
itemB._name = "Act One"
itemB._parent = "a000000000001"
itemB._type = nwItemType.FOLDER
itemB._class = nwItemClass.NOVEL
itemB._expanded = True
itemC = NWItem(theProject)
itemC = NWItem(theProject, "c000000000001")
itemC._name = "Chapter One"
itemC._parent = "b000000000001"
itemC._type = nwItemType.FILE
itemC._class = nwItemClass.NOVEL
itemC._layout = nwItemLayout.DOCUMENT
@@ -60,8 +63,9 @@ def mockItems(mockGUI, mockRnd):
itemC._wordCount = 50
itemC._paraCount = 2
itemD = NWItem(theProject)
itemD = NWItem(theProject, "c000000000002")
itemD._name = "Scene One"
itemD._parent = "b000000000001"
itemD._type = nwItemType.FILE
itemD._class = nwItemClass.NOVEL
itemD._layout = nwItemLayout.DOCUMENT
@@ -69,26 +73,30 @@ def mockItems(mockGUI, mockRnd):
itemD._wordCount = 500
itemD._paraCount = 20
itemE = NWItem(theProject)
itemE = NWItem(theProject, "a000000000002")
itemE._name = "Outtakes"
itemE._parent = None
itemE._type = nwItemType.ROOT
itemE._class = nwItemClass.ARCHIVE
itemE._expanded = False
itemF = NWItem(theProject)
itemF = NWItem(theProject, "a000000000003")
itemF._name = "Trash"
itemF._parent = None
itemF._type = nwItemType.ROOT
itemF._class = nwItemClass.TRASH
itemF._expanded = False
itemG = NWItem(theProject)
itemG = NWItem(theProject, "a000000000004")
itemG._name = "Characters"
itemG._parent = None
itemG._type = nwItemType.ROOT
itemG._class = nwItemClass.CHARACTER
itemG._expanded = True
itemH = NWItem(theProject)
itemH = NWItem(theProject, "b000000000002")
itemH._name = "Jane Doe"
itemH._parent = "a000000000004"
itemH._type = nwItemType.FILE
itemH._class = nwItemClass.CHARACTER
itemH._layout = nwItemLayout.NOTE
@@ -96,18 +104,7 @@ def mockItems(mockGUI, mockRnd):
itemH._wordCount = 400
itemH._paraCount = 16
theItems = [
("a000000000001", None, itemA),
("b000000000001", "a000000000001", itemB),
("c000000000001", "b000000000001", itemC),
("c000000000002", "b000000000001", itemD),
("a000000000002", None, itemE),
("a000000000003", None, itemF),
("a000000000004", None, itemG),
("b000000000002", "a000000000004", itemH),
]
return theItems
return [itemA, itemB, itemC, itemD, itemE, itemF, itemG, itemH]
@pytest.mark.core
@@ -123,10 +120,10 @@ def testCoreTree_BuildTree(mockGUI, mockItems):
assert theTree.trashRoot() is None
aHandles = []
for tHandle, pHandle, nwItem in mockItems:
aHandles.append(tHandle)
assert theTree.append(tHandle, pHandle, nwItem) is True
assert theTree.updateItemData(tHandle) is True
for nwItem in mockItems:
aHandles.append(nwItem.itemHandle)
assert theTree.append(nwItem) is True
assert theTree.updateItemData(nwItem.itemHandle) is True
assert theTree._treeChanged is True
@@ -143,6 +140,9 @@ def testCoreTree_BuildTree(mockGUI, mockItems):
for theItem, theHandle in zip(theTree, aHandles):
assert theItem.itemHandle == theHandle
# Trash Folder
# ============
# Check that we have the correct archive and trash folders
assert theTree.trashRoot() == "a000000000003"
assert theTree.findRoot(nwItemClass.ARCHIVE) == "a000000000002"
@@ -157,57 +157,85 @@ def testCoreTree_BuildTree(mockGUI, mockItems):
assert theTree.isTrash("0000000000000") is True # Doesn't exist
assert theTree.isTrash("a000000000003") is True # This the trash folder
theTree["a000000000003"].setClass(nwItemClass.NO_CLASS)
theTree["a000000000003"].setClass(nwItemClass.NO_CLASS) # type: ignore
assert theTree.isTrash("a000000000003") is True # This is still trash
theTree["a000000000003"].setClass(nwItemClass.TRASH)
theTree["a000000000003"].setClass(nwItemClass.TRASH) # type: ignore
assert theTree.isTrash("b000000000002") is False # This is not trash
value = theTree["b000000000002"].itemParent
theTree["b000000000002"].setParent("a000000000003")
value = theTree["b000000000002"].itemParent # type: ignore
theTree["b000000000002"].setParent("a000000000003") # type: ignore
assert theTree.isTrash("b000000000002") is True # This is in trash
theTree["b000000000002"].setParent(value)
theTree["b000000000002"].setParent(value) # type: ignore
value = theTree["b000000000002"].itemRoot
theTree["b000000000002"].setRoot("a000000000003")
value = theTree["b000000000002"].itemRoot # type: ignore
theTree["b000000000002"].setRoot("a000000000003") # type: ignore
assert theTree.isTrash("b000000000002") is True # This is in trash
theTree["b000000000002"].setRoot(value)
theTree["b000000000002"].setRoot(value) # type: ignore
# Try to add another trash folder
itemT = NWItem(theProject)
itemT = NWItem(theProject, "1111111111111")
itemT._name = "Trash"
itemT._type = nwItemType.ROOT
itemT._class = nwItemClass.TRASH
itemT._expanded = False
assert theTree.append("1234567890abc", None, itemT) is False
assert theTree.append(itemT) is False
assert len(theTree) == len(mockItems)
# Generate handle automatically
itemT = NWItem(theProject)
itemT._name = "New File"
itemT._type = nwItemType.FILE
itemT._class = nwItemClass.NOVEL
itemT._layout = nwItemLayout.DOCUMENT
# Create or Add Items
# ===================
assert theTree.append(None, None, itemT) is True
assert theTree.updateItemData(itemT.itemHandle) is True
assert len(theTree) == len(mockItems) + 1
# Create a new item, but with invalid parent
assert theTree.create("New File", "blabla", nwItemType.FILE, nwItemClass.NO_CLASS) is None
# Create a new, valid item
nHandle = theTree.create("New File", "b000000000001", nwItemType.FILE, nwItemClass.NO_CLASS)
assert isHandle(nHandle)
assert nHandle == "0000000000000"
# The new item should be the last item in the tree
theList = theTree.handles()
nHandle = "0000000000000"
assert theList[-1] == nHandle
# Try to add existing handle
assert theTree.append(nHandle, None, itemT) is False
# Retrieve the item
itemT = theTree[nHandle]
assert isinstance(itemT, NWItem)
assert len(theTree) == len(mockItems) + 1
# We should not be allowed to add the item again
assert theTree.append(itemT) is False
assert len(theTree) == len(mockItems) + 1
# Create an invalid item to add, which will be rejected
itemU = NWItem.duplicate(itemT, "blabla")
assert theTree.append(itemU) is False
assert len(theTree) == len(mockItems) + 1
# Duplicate Items
# ===============
# Duplicate a non-existing item
assert theTree.duplicate("blabla") is None
# Duplicate the new item
itemV = theTree.duplicate(nHandle)
assert isinstance(itemV, NWItem)
assert len(theTree) == len(mockItems) + 2
dHandle = itemV.itemHandle
assert dHandle == "0000000000001"
# Delete Items
# ============
# Delete a non-existing item
del theTree["stuff"]
assert len(theTree) == len(mockItems) + 1
assert len(theTree) == len(mockItems) + 2
# Delete the last item
# Delete the last items
del theTree[nHandle]
del theTree[dHandle]
assert len(theTree) == len(mockItems)
assert nHandle not in theTree
@@ -235,17 +263,17 @@ def testCoreTree_PackUnpack(mockGUI, mockItems):
theTree = NWTree(theProject)
aHandles = []
for tHandle, pHandle, nwItem in mockItems:
aHandles.append(tHandle)
theTree.append(tHandle, pHandle, nwItem)
theTree.updateItemData(tHandle)
for nwItem in mockItems:
aHandles.append(nwItem.itemHandle)
theTree.append(nwItem)
theTree.updateItemData(nwItem.itemHandle)
assert len(theTree) == len(mockItems)
# Pack
tree = theTree.pack()
for i, (tHandle, pHandle, nwItem) in enumerate(mockItems):
assert tree[i]["itemAttr"]["handle"] == tHandle
for i, nwItem in enumerate(mockItems):
assert tree[i]["itemAttr"]["handle"] == nwItem.itemHandle
# Unpack
theTree.clear()
@@ -263,9 +291,9 @@ def testCoreTree_Methods(mockGUI, mockItems):
theProject = NWProject(mockGUI)
theTree = NWTree(theProject)
for tHandle, pHandle, nwItem in mockItems:
theTree.append(tHandle, pHandle, nwItem)
theTree.updateItemData(tHandle)
for nwItem in mockItems:
theTree.append(nwItem)
theTree.updateItemData(nwItem.itemHandle)
assert len(theTree) == len(mockItems)
@@ -273,22 +301,22 @@ def testCoreTree_Methods(mockGUI, mockItems):
assert theTree.updateItemData("stuff") is False
# Update item data, invalid item parent
corrParent = theTree["b000000000001"].itemParent
theTree["b000000000001"].setParent("0000000000000")
corrParent = theTree["b000000000001"].itemParent # type: ignore
theTree["b000000000001"].setParent("0000000000000") # type: ignore
assert theTree.updateItemData("b000000000001") is False
# Update item data, valid item parent
theTree["b000000000001"].setParent(corrParent)
theTree["b000000000001"].setParent(corrParent) # type: ignore
assert theTree.updateItemData("b000000000001") is True
# Update item data, root is unreachable
maxDepth = theTree.MAX_DEPTH
theTree.MAX_DEPTH = 0
theTree.MAX_DEPTH = 0 # type: ignore
with pytest.raises(RecursionError):
theTree.updateItemData("b000000000001")
theTree.MAX_DEPTH = maxDepth
# Chech type
# Check type
assert theTree.checkType("blabla", nwItemType.FILE) is False
assert theTree.checkType("b000000000001", nwItemType.FILE) is False
assert theTree.checkType("c000000000001", nwItemType.FILE) is True
@@ -306,7 +334,7 @@ def testCoreTree_Methods(mockGUI, mockItems):
assert roots[3][0] == "a000000000004"
# Add a fake item to root and check that it can handle it
theTree._treeRoots["0000000000000"] = NWItem(theProject)
theTree._treeRoots["0000000000000"] = NWItem(theProject, "0000000000000")
assert theTree.findRoot(nwItemClass.WORLD) is None
del theTree._treeRoots["0000000000000"]
@@ -318,18 +346,18 @@ def testCoreTree_Methods(mockGUI, mockItems):
# Cause recursion error
maxDepth = theTree.MAX_DEPTH
theTree.MAX_DEPTH = 0
theTree.MAX_DEPTH = 0 # type: ignore
with pytest.raises(RecursionError):
theTree.getItemPath("c000000000001")
theTree.MAX_DEPTH = maxDepth
# Break the folder parent handle
theTree["b000000000001"]._parent = "stuff"
theTree["b000000000001"]._parent = "stuff" # type: ignore
assert theTree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001"
]
theTree["b000000000001"]._parent = "a000000000001"
theTree["b000000000001"]._parent = "a000000000001" # type: ignore
assert theTree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001", "a000000000001"
]
@@ -349,13 +377,13 @@ def testCoreTree_MakeHandles(mockGUI):
random.seed(42)
tHandle = theTree._makeHandle()
assert tHandle == handles[0]
theTree._projTree[handles[0]] = None
theTree._projTree[handles[0]] = None # type: ignore
# Add the next in line to the project to force duplicate
theTree._projTree[handles[1]] = None
theTree._projTree[handles[1]] = None # type: ignore
tHandle = theTree._makeHandle()
assert tHandle == handles[2]
theTree._projTree[handles[2]] = None
theTree._projTree[handles[2]] = None # type: ignore
# Reset the seed to force collissions, which should still end up
# returning the next handle in the sequence
@@ -372,8 +400,8 @@ def testCoreTree_Stats(mockGUI, mockItems):
theProject = NWProject(mockGUI)
theTree = NWTree(theProject)
for tHandle, pHandle, nwItem in mockItems:
theTree.append(tHandle, pHandle, nwItem)
for nwItem in mockItems:
theTree.append(nwItem)
assert len(theTree) == len(mockItems)
theTree._treeOrder.append("stuff")
@@ -393,9 +421,9 @@ def testCoreTree_Reorder(caplog, mockGUI, mockItems):
theTree = NWTree(theProject)
aHandle = []
for tHandle, pHandle, nwItem in mockItems:
aHandle.append(tHandle)
theTree.append(tHandle, pHandle, nwItem)
for nwItem in mockItems:
aHandle.append(nwItem.itemHandle)
theTree.append(nwItem)
assert len(theTree) == len(mockItems)
@@ -422,14 +450,14 @@ def testCoreTree_Reorder(caplog, mockGUI, mockItems):
@pytest.mark.core
def testCoreTree_ToCFile(monkeypatch, tstPaths, mockGUI, mockItems):
def testCoreTree_ToCFile(monkeypatch, fncPath, mockGUI, mockItems):
"""Test writing the ToC.txt file."""
theProject = NWProject(mockGUI)
theTree = NWTree(theProject)
for tHandle, pHandle, nwItem in mockItems:
theTree.append(tHandle, pHandle, nwItem)
theTree.updateItemData(tHandle)
for nwItem in mockItems:
theTree.append(nwItem)
theTree.updateItemData(nwItem.itemHandle)
assert len(theTree) == len(mockItems)
theTree._treeOrder.append("stuff")
@@ -443,24 +471,27 @@ def testCoreTree_ToCFile(monkeypatch, tstPaths, mockGUI, mockItems):
return dItem.itemType == nwItemType.FILE
monkeypatch.setattr("pathlib.Path.is_file", mockIsFile)
theProject._storage._runtimePath = fncPath
(fncPath / "content").mkdir()
theProject._storage._runtimePath = None
assert theTree.writeToCFile() is False
# Block extraction of the path
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", lambda *a: None)
assert theTree.writeToCFile() is False
theProject._storage._runtimePath = tstPaths.tmpDir
# Block opening the file
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert theTree.writeToCFile() is False
theProject._storage._runtimePath = tstPaths.tmpDir
(tstPaths.tmpDir / "content").mkdir()
# Allow writing
assert theTree.writeToCFile() is True
pathA = str(Path("content") / "c000000000001.nwd")
pathB = str(Path("content") / "c000000000002.nwd")
pathC = str(Path("content") / "b000000000002.nwd")
assert readFile(tstPaths.tmpDir / nwFiles.TOC_TXT) == (
assert (fncPath / nwFiles.TOC_TXT).read_text() == (
"\n"
"Table of Contents\n"
"=================\n"