Fix tests broken by xml rewrite
This commit is contained in:
@@ -190,7 +190,7 @@ class NWItem:
|
|||||||
if "handle" in data:
|
if "handle" in data:
|
||||||
self.setHandle(data["handle"])
|
self.setHandle(data["handle"])
|
||||||
else:
|
else:
|
||||||
logger.error("XML item entry does not have a handle")
|
logger.error("Item does not have a handle")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.setName(data.get("label", ""))
|
self.setName(data.get("label", ""))
|
||||||
@@ -217,12 +217,14 @@ class NWItem:
|
|||||||
self._parent = None # Root items cannot have a parent
|
self._parent = None # Root items cannot have a parent
|
||||||
|
|
||||||
if self._type != nwItemType.FILE:
|
if self._type != nwItemType.FILE:
|
||||||
self._heading = "H0" # Only files have headers
|
# Reset values that should only be set for files
|
||||||
self._active = False # Can only be True for files
|
self._layout = nwItemLayout.NO_LAYOUT
|
||||||
self._charCount = 0 # Only set for files
|
self._heading = "H0"
|
||||||
self._wordCount = 0 # Only set for files
|
self._active = False
|
||||||
self._paraCount = 0 # Only set for files
|
self._charCount = 0
|
||||||
self._cursorPos = 0 # Only set for files
|
self._wordCount = 0
|
||||||
|
self._paraCount = 0
|
||||||
|
self._cursorPos = 0
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
+181
-241
@@ -21,8 +21,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from lxml import etree
|
|
||||||
|
|
||||||
from PyQt5.QtGui import QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
|
|
||||||
from tools import C, buildTestProject
|
from tools import C, buildTestProject
|
||||||
@@ -497,257 +495,199 @@ def testCoreItem_ClassDefaults(mockGUI):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
@pytest.mark.skip
|
def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
|
||||||
def testCoreItem_XMLPackUnpack(mockGUI, caplog, mockRnd):
|
"""Test packing and unpacking entries for the NWItem class.
|
||||||
"""Test packing and unpacking XML objects for the NWItem class.
|
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
nwXML = etree.Element("novelWriterXML")
|
theProject.data.itemStatus.write(None, "New", (100, 100, 100))
|
||||||
|
theProject.data.itemImport.write(None, "New", (100, 100, 100))
|
||||||
|
|
||||||
statusKeys = ["s000000", "s000001", "s000002", "s000003"]
|
# Invalid
|
||||||
importKeys = ["i000004", "i000005", "i000006", "i000007"]
|
theItem = NWItem(theProject)
|
||||||
|
assert theItem.unpack({}) is False
|
||||||
|
|
||||||
# File
|
# File
|
||||||
# ====
|
|
||||||
|
|
||||||
theItem = NWItem(theProject)
|
theItem = NWItem(theProject)
|
||||||
theItem.setHandle("0123456789abc")
|
assert theItem.unpack({
|
||||||
theItem.setParent("0123456789abc")
|
"label": "A File",
|
||||||
theItem.setRoot("0123456789abc")
|
"handle": "0000000000003",
|
||||||
theItem.setOrder(1)
|
"parent": "0000000000002",
|
||||||
theItem.setName("A Name")
|
"root": "0000000000001",
|
||||||
theItem.setClass("NOVEL")
|
"order": 1,
|
||||||
theItem.setType("FILE")
|
"type": "FILE",
|
||||||
theItem.setImport(importKeys[3])
|
"class": "NOVEL",
|
||||||
theItem.setLayout("NOTE")
|
"layout": "DOCUMENT",
|
||||||
theItem.setActive(False)
|
"expanded": True,
|
||||||
theItem.setParaCount(3)
|
"status": None,
|
||||||
theItem.setWordCount(5)
|
"import": None,
|
||||||
theItem.setCharCount(7)
|
"heading": "H1",
|
||||||
theItem.setCursorPos(11)
|
"charCount": 100,
|
||||||
|
"wordCount": 20,
|
||||||
|
"paraCount": 2,
|
||||||
|
"cursorPos": 50,
|
||||||
|
"active": False,
|
||||||
|
}) is True
|
||||||
|
|
||||||
# Pack
|
assert theItem.itemName == "A File"
|
||||||
xContent = etree.SubElement(nwXML, "content")
|
assert theItem.itemHandle == "0000000000003"
|
||||||
theItem.packXML(xContent)
|
assert theItem.itemParent == "0000000000002"
|
||||||
assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == (
|
assert theItem.itemRoot == "0000000000001"
|
||||||
b'<content>'
|
|
||||||
b'<item handle="0123456789abc" parent="0123456789abc" root="0123456789abc" order="1" '
|
|
||||||
b'type="FILE" class="NOVEL" layout="NOTE"><meta expanded="False" mainHeading="H0" '
|
|
||||||
b'charCount="7" wordCount="5" paraCount="3" cursorPos="11"/><name status="None" '
|
|
||||||
b'import="%s" active="False">A Name</name></item>'
|
|
||||||
b'</content>'
|
|
||||||
) % bytes(importKeys[3], encoding="utf8")
|
|
||||||
|
|
||||||
# Unpack
|
|
||||||
theItem = NWItem(theProject)
|
|
||||||
assert theItem.unpackXML(xContent[0])
|
|
||||||
assert theItem.itemHandle == "0123456789abc"
|
|
||||||
assert theItem.itemParent == "0123456789abc"
|
|
||||||
assert theItem.itemRoot == "0123456789abc"
|
|
||||||
assert theItem.itemOrder == 1
|
assert theItem.itemOrder == 1
|
||||||
|
assert theItem.itemType == nwItemType.FILE
|
||||||
|
assert theItem.itemClass == nwItemClass.NOVEL
|
||||||
|
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
||||||
|
assert theItem.itemStatus == "s000000"
|
||||||
|
assert theItem.itemImport == "i000001"
|
||||||
assert theItem.isActive is False
|
assert theItem.isActive is False
|
||||||
assert theItem.paraCount == 3
|
|
||||||
assert theItem.wordCount == 5
|
|
||||||
assert theItem.charCount == 7
|
|
||||||
assert theItem.cursorPos == 11
|
|
||||||
assert theItem.itemClass == nwItemClass.NOVEL
|
|
||||||
assert theItem.itemType == nwItemType.FILE
|
|
||||||
assert theItem.itemLayout == nwItemLayout.NOTE
|
|
||||||
assert theItem.itemStatus == statusKeys[0] # Was None, should now be default
|
|
||||||
assert theItem.itemImport == importKeys[3]
|
|
||||||
|
|
||||||
# Folder
|
|
||||||
# ======
|
|
||||||
|
|
||||||
theItem = NWItem(theProject)
|
|
||||||
theItem.setHandle("0123456789abc")
|
|
||||||
theItem.setParent("0123456789abc")
|
|
||||||
theItem.setRoot("0123456789abc")
|
|
||||||
theItem.setOrder(1)
|
|
||||||
theItem.setName("A Name")
|
|
||||||
theItem.setClass("NOVEL")
|
|
||||||
theItem.setType("FOLDER")
|
|
||||||
theItem.setStatus(statusKeys[1])
|
|
||||||
theItem.setLayout("NOTE")
|
|
||||||
theItem.setExpanded(True)
|
|
||||||
theItem.setActive(False)
|
|
||||||
theItem.setParaCount(3)
|
|
||||||
theItem.setWordCount(5)
|
|
||||||
theItem.setCharCount(7)
|
|
||||||
theItem.setCursorPos(11)
|
|
||||||
|
|
||||||
# Pack
|
|
||||||
xContent = etree.SubElement(nwXML, "content")
|
|
||||||
theItem.packXML(xContent)
|
|
||||||
assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == (
|
|
||||||
b'<content>'
|
|
||||||
b'<item handle="0123456789abc" parent="0123456789abc" root="0123456789abc" order="1" '
|
|
||||||
b'type="FOLDER" class="NOVEL"><meta expanded="True"/><name status="%s" '
|
|
||||||
b'import="None">A Name</name></item>'
|
|
||||||
b'</content>'
|
|
||||||
) % bytes(statusKeys[1], encoding="utf8")
|
|
||||||
|
|
||||||
# Unpack
|
|
||||||
theItem = NWItem(theProject)
|
|
||||||
assert theItem.unpackXML(xContent[0])
|
|
||||||
assert theItem.itemHandle == "0123456789abc"
|
|
||||||
assert theItem.itemParent == "0123456789abc"
|
|
||||||
assert theItem.itemRoot == "0123456789abc"
|
|
||||||
assert theItem.itemOrder == 1
|
|
||||||
assert theItem.isExpanded is True
|
assert theItem.isExpanded is True
|
||||||
assert theItem.isActive is True
|
assert theItem.mainHeading == "H1"
|
||||||
assert theItem.paraCount == 0
|
assert theItem.charCount == 100
|
||||||
assert theItem.wordCount == 0
|
assert theItem.wordCount == 20
|
||||||
assert theItem.charCount == 0
|
assert theItem.paraCount == 2
|
||||||
assert theItem.cursorPos == 0
|
|
||||||
assert theItem.itemClass == nwItemClass.NOVEL
|
|
||||||
assert theItem.itemType == nwItemType.FOLDER
|
|
||||||
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
|
||||||
assert theItem.itemStatus == statusKeys[1]
|
|
||||||
assert theItem.itemImport == importKeys[0] # Was None, should now be default
|
|
||||||
|
|
||||||
# Errors
|
|
||||||
# ======
|
|
||||||
|
|
||||||
# Not an Item
|
|
||||||
mockXml = etree.SubElement(nwXML, "stuff")
|
|
||||||
assert theItem.unpackXML(mockXml) is False
|
|
||||||
|
|
||||||
# Item without Handle
|
|
||||||
mockXml = etree.SubElement(nwXML, "item", attrib={"stuff": "nah"})
|
|
||||||
assert theItem.unpackXML(mockXml) is False
|
|
||||||
|
|
||||||
# Item with Invalid SubElement is Accepted w/Error
|
|
||||||
mockXml = etree.SubElement(nwXML, "item", attrib={"handle": "0123456789abc"})
|
|
||||||
xParam = etree.SubElement(mockXml, "invalid")
|
|
||||||
xParam.text = "stuff"
|
|
||||||
caplog.clear()
|
|
||||||
assert theItem.unpackXML(mockXml) is True
|
|
||||||
assert "Unknown tag 'invalid'" in caplog.text
|
|
||||||
|
|
||||||
# Pack Valid Item
|
|
||||||
mockXml = etree.SubElement(nwXML, "group")
|
|
||||||
theItem._subPack(mockXml, "subGroup", {"one": "two"}, "value", False)
|
|
||||||
assert etree.tostring(mockXml, pretty_print=False, encoding="utf-8") == (
|
|
||||||
b"<group><subGroup one=\"two\">value</subGroup></group>"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Pack Not Allowed None
|
|
||||||
mockXml = etree.SubElement(nwXML, "group")
|
|
||||||
assert theItem._subPack(mockXml, "subGroup", {}, None, False) is None
|
|
||||||
assert theItem._subPack(mockXml, "subGroup", {}, "None", False) is None
|
|
||||||
assert etree.tostring(mockXml, pretty_print=False, encoding="utf-8") == (
|
|
||||||
b"<group/>"
|
|
||||||
)
|
|
||||||
|
|
||||||
# END Test testCoreItem_XMLPackUnpack
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
|
||||||
@pytest.mark.skip
|
|
||||||
def testCoreItem_ConvertFromFmt12(mockGUI):
|
|
||||||
"""Test the setter for all the nwItemLayout values for the NWItem
|
|
||||||
class using the class names that were present in file format 1.2.
|
|
||||||
"""
|
|
||||||
theProject = NWProject(mockGUI)
|
|
||||||
theItem = NWItem(theProject)
|
|
||||||
|
|
||||||
# Deprecated Layouts
|
|
||||||
theItem.setLayout("TITLE")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
|
||||||
theItem.setLayout("PAGE")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
|
||||||
theItem.setLayout("BOOK")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
|
||||||
theItem.setLayout("PARTITION")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
|
||||||
theItem.setLayout("UNNUMBERED")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
|
||||||
theItem.setLayout("CHAPTER")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
|
||||||
theItem.setLayout("SCENE")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
|
||||||
theItem.setLayout("MUMBOJUMBO")
|
|
||||||
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
|
||||||
|
|
||||||
# END Test testCoreItem_ConvertFromFmt12
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
|
||||||
@pytest.mark.skip
|
|
||||||
def testCoreItem_ConvertFromFmt13(mockGUI):
|
|
||||||
"""Test packing and unpacking XML objects for the NWItem class from
|
|
||||||
format version 1.3
|
|
||||||
"""
|
|
||||||
theProject = NWProject(mockGUI)
|
|
||||||
|
|
||||||
# Make Version 1.3 XML
|
|
||||||
nwXML = etree.Element("novelWriterXML")
|
|
||||||
xContent = etree.SubElement(nwXML, "content")
|
|
||||||
|
|
||||||
# Folder
|
|
||||||
xPack = etree.SubElement(xContent, "item", attrib={
|
|
||||||
"handle": "a000000000001",
|
|
||||||
"order": "1",
|
|
||||||
"parent": "b000000000001",
|
|
||||||
})
|
|
||||||
NWItem._subPack(xPack, "name", text="Folder")
|
|
||||||
NWItem._subPack(xPack, "type", text="FOLDER")
|
|
||||||
NWItem._subPack(xPack, "class", text="NOVEL")
|
|
||||||
NWItem._subPack(xPack, "status", text="New")
|
|
||||||
NWItem._subPack(xPack, "expanded", text="True")
|
|
||||||
|
|
||||||
# Unpack Folder
|
|
||||||
theItem = NWItem(theProject)
|
|
||||||
theItem.unpackXML(xContent[0])
|
|
||||||
assert theItem.itemHandle == "a000000000001"
|
|
||||||
assert theItem.itemParent == "b000000000001"
|
|
||||||
assert theItem.itemOrder == 1
|
|
||||||
assert theItem.isExpanded is True
|
|
||||||
assert theItem.isActive is True
|
|
||||||
assert theItem.charCount == 0
|
|
||||||
assert theItem.wordCount == 0
|
|
||||||
assert theItem.paraCount == 0
|
|
||||||
assert theItem.cursorPos == 0
|
|
||||||
assert theItem.itemClass == nwItemClass.NOVEL
|
|
||||||
assert theItem.itemType == nwItemType.FOLDER
|
|
||||||
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
|
||||||
|
|
||||||
# File
|
|
||||||
xPack = etree.SubElement(xContent, "item", attrib={
|
|
||||||
"handle": "c000000000001",
|
|
||||||
"order": "2",
|
|
||||||
"parent": "a000000000001",
|
|
||||||
})
|
|
||||||
NWItem._subPack(xPack, "name", text="Scene")
|
|
||||||
NWItem._subPack(xPack, "type", text="FILE")
|
|
||||||
NWItem._subPack(xPack, "class", text="NOVEL")
|
|
||||||
NWItem._subPack(xPack, "status", text="New")
|
|
||||||
NWItem._subPack(xPack, "exported", text="True")
|
|
||||||
NWItem._subPack(xPack, "layout", text="DOCUMENT")
|
|
||||||
NWItem._subPack(xPack, "charCount", text="600")
|
|
||||||
NWItem._subPack(xPack, "wordCount", text="100")
|
|
||||||
NWItem._subPack(xPack, "paraCount", text="6")
|
|
||||||
NWItem._subPack(xPack, "cursorPos", text="50")
|
|
||||||
|
|
||||||
# Unpack File
|
|
||||||
theItem = NWItem(theProject)
|
|
||||||
theItem.unpackXML(xContent[1])
|
|
||||||
assert theItem.itemHandle == "c000000000001"
|
|
||||||
assert theItem.itemParent == "a000000000001"
|
|
||||||
assert theItem.itemOrder == 2
|
|
||||||
assert theItem.isExpanded is False
|
|
||||||
assert theItem.isActive is True
|
|
||||||
assert theItem.charCount == 600
|
|
||||||
assert theItem.wordCount == 100
|
|
||||||
assert theItem.paraCount == 6
|
|
||||||
assert theItem.cursorPos == 50
|
assert theItem.cursorPos == 50
|
||||||
|
|
||||||
|
assert theItem.pack() == {
|
||||||
|
"name": "A File",
|
||||||
|
"itemAttr": {
|
||||||
|
"handle": "0000000000003",
|
||||||
|
"parent": "0000000000002",
|
||||||
|
"root": "0000000000001",
|
||||||
|
"order": "1",
|
||||||
|
"type": "FILE",
|
||||||
|
"class": "NOVEL",
|
||||||
|
"layout": "DOCUMENT",
|
||||||
|
},
|
||||||
|
"metaAttr": {
|
||||||
|
"expanded": "True",
|
||||||
|
"heading": "H1",
|
||||||
|
"charCount": "100",
|
||||||
|
"wordCount": "20",
|
||||||
|
"paraCount": "2",
|
||||||
|
"cursorPos": "50",
|
||||||
|
},
|
||||||
|
"nameAttr": {
|
||||||
|
"status": "s000000",
|
||||||
|
"import": "i000001",
|
||||||
|
"active": "False",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Folder
|
||||||
|
theItem = NWItem(theProject)
|
||||||
|
assert theItem.unpack({
|
||||||
|
"label": "A Folder",
|
||||||
|
"handle": "0000000000003",
|
||||||
|
"parent": "0000000000002",
|
||||||
|
"root": "0000000000001",
|
||||||
|
"order": 1,
|
||||||
|
"type": "FOLDER",
|
||||||
|
"class": "NOVEL",
|
||||||
|
"layout": "DOCUMENT",
|
||||||
|
"expanded": True,
|
||||||
|
"status": "",
|
||||||
|
"import": "",
|
||||||
|
"heading": "H1",
|
||||||
|
"charCount": 100,
|
||||||
|
"wordCount": 20,
|
||||||
|
"paraCount": 2,
|
||||||
|
"cursorPos": 50,
|
||||||
|
"active": True,
|
||||||
|
}) is True
|
||||||
|
|
||||||
|
assert theItem.itemName == "A Folder"
|
||||||
|
assert theItem.itemHandle == "0000000000003"
|
||||||
|
assert theItem.itemParent == "0000000000002"
|
||||||
|
assert theItem.itemRoot == "0000000000001"
|
||||||
|
assert theItem.itemOrder == 1
|
||||||
|
assert theItem.itemType == nwItemType.FOLDER
|
||||||
assert theItem.itemClass == nwItemClass.NOVEL
|
assert theItem.itemClass == nwItemClass.NOVEL
|
||||||
assert theItem.itemType == nwItemType.FILE
|
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
assert theItem.itemStatus == "s000000"
|
||||||
|
assert theItem.itemImport == "i000001"
|
||||||
|
assert theItem.isActive is False
|
||||||
|
assert theItem.isExpanded is True
|
||||||
|
assert theItem.mainHeading == "H0"
|
||||||
|
assert theItem.charCount == 0
|
||||||
|
assert theItem.wordCount == 0
|
||||||
|
assert theItem.paraCount == 0
|
||||||
|
assert theItem.cursorPos == 0
|
||||||
|
|
||||||
# Deprecated Type
|
assert theItem.pack() == {
|
||||||
theItem.setType("TRASH")
|
"name": "A Folder",
|
||||||
|
"itemAttr": {
|
||||||
|
"handle": "0000000000003",
|
||||||
|
"parent": "0000000000002",
|
||||||
|
"root": "0000000000001",
|
||||||
|
"order": "1",
|
||||||
|
"type": "FOLDER",
|
||||||
|
"class": "NOVEL",
|
||||||
|
},
|
||||||
|
"metaAttr": {
|
||||||
|
"expanded": "True",
|
||||||
|
},
|
||||||
|
"nameAttr": {
|
||||||
|
"status": "s000000",
|
||||||
|
"import": "i000001",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Root
|
||||||
|
theItem = NWItem(theProject)
|
||||||
|
assert theItem.unpack({
|
||||||
|
"label": "A Novel",
|
||||||
|
"handle": "0000000000003",
|
||||||
|
"parent": "0000000000002",
|
||||||
|
"root": "0000000000001",
|
||||||
|
"order": 1,
|
||||||
|
"type": "ROOT",
|
||||||
|
"class": "NOVEL",
|
||||||
|
"layout": "DOCUMENT",
|
||||||
|
"expanded": True,
|
||||||
|
"status": None,
|
||||||
|
"import": None,
|
||||||
|
"heading": "H1",
|
||||||
|
"charCount": 100,
|
||||||
|
"wordCount": 20,
|
||||||
|
"paraCount": 2,
|
||||||
|
"cursorPos": 50,
|
||||||
|
"active": True,
|
||||||
|
}) is True
|
||||||
|
|
||||||
|
assert theItem.itemName == "A Novel"
|
||||||
|
assert theItem.itemHandle == "0000000000003"
|
||||||
|
assert theItem.itemParent is None
|
||||||
|
assert theItem.itemRoot == "0000000000003"
|
||||||
|
assert theItem.itemOrder == 1
|
||||||
assert theItem.itemType == nwItemType.ROOT
|
assert theItem.itemType == nwItemType.ROOT
|
||||||
|
assert theItem.itemClass == nwItemClass.NOVEL
|
||||||
|
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||||
|
assert theItem.itemStatus == "s000000"
|
||||||
|
assert theItem.itemImport == "i000001"
|
||||||
|
assert theItem.isActive is False
|
||||||
|
assert theItem.isExpanded is True
|
||||||
|
assert theItem.mainHeading == "H0"
|
||||||
|
assert theItem.charCount == 0
|
||||||
|
assert theItem.wordCount == 0
|
||||||
|
assert theItem.paraCount == 0
|
||||||
|
assert theItem.cursorPos == 0
|
||||||
|
|
||||||
# END Test testCoreItem_ConvertFromFmt13
|
assert theItem.pack() == {
|
||||||
|
"name": "A Novel",
|
||||||
|
"itemAttr": {
|
||||||
|
"handle": "0000000000003",
|
||||||
|
"parent": "None",
|
||||||
|
"root": "0000000000003",
|
||||||
|
"order": "1",
|
||||||
|
"type": "ROOT",
|
||||||
|
"class": "NOVEL",
|
||||||
|
},
|
||||||
|
"metaAttr": {
|
||||||
|
"expanded": "True",
|
||||||
|
},
|
||||||
|
"nameAttr": {
|
||||||
|
"status": "s000000",
|
||||||
|
"import": "i000001",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# END Test testCoreItem_PackUnpack
|
||||||
|
|||||||
@@ -20,13 +20,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from tools import cmpFiles, writeFile, readFile, buildTestProject, XML_IGNORE, C
|
|
||||||
from mock import causeOSError
|
from mock import causeOSError
|
||||||
|
from tools import cmpFiles, writeFile, readFile, buildTestProject, XML_IGNORE, C
|
||||||
|
|
||||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
||||||
from novelwriter.common import formatTimeStamp
|
from novelwriter.common import formatTimeStamp
|
||||||
@@ -36,6 +37,7 @@ from novelwriter.core.index import NWIndex
|
|||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.core.options import OptionState
|
from novelwriter.core.options import OptionState
|
||||||
from novelwriter.core.document import NWDoc
|
from novelwriter.core.document import NWDoc
|
||||||
|
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter, XMLReadState
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
@@ -380,140 +382,90 @@ def testCoreProject_NewFileFolder(monkeypatch, fncDir, outDir, refDir, mockGUI,
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
@pytest.mark.skip
|
def testCoreProject_Open(monkeypatch, caplog, mockGUI, fncDir, mockRnd):
|
||||||
def testCoreProject_Open(monkeypatch, nwMinimal, mockGUI):
|
|
||||||
"""Test opening a project.
|
"""Test opening a project.
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
|
mockRnd.reset()
|
||||||
|
buildTestProject(theProject, fncDir)
|
||||||
|
|
||||||
# Rename the project file to check handling
|
# Rename the project file to check handling
|
||||||
rName = os.path.join(nwMinimal, nwFiles.PROJ_FILE)
|
rName = os.path.join(fncDir, nwFiles.PROJ_FILE)
|
||||||
wName = os.path.join(nwMinimal, nwFiles.PROJ_FILE+"_sdfghj")
|
wName = os.path.join(fncDir, nwFiles.PROJ_FILE+"_sdfghj")
|
||||||
os.rename(rName, wName)
|
os.rename(rName, wName)
|
||||||
assert theProject.openProject(nwMinimal) is False
|
assert theProject.openProject(fncDir) is False
|
||||||
os.rename(wName, rName)
|
os.rename(wName, rName)
|
||||||
|
|
||||||
# Fail on folder structure check
|
# Fail on folder structure check
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("os.mkdir", causeOSError)
|
mp.setattr("os.mkdir", causeOSError)
|
||||||
assert theProject.openProject(nwMinimal) is False
|
shutil.rmtree(os.path.join(fncDir, "meta"))
|
||||||
|
assert theProject.openProject(fncDir) is False
|
||||||
|
|
||||||
# Fail on lock file
|
# Fail on lock file
|
||||||
theProject.setProjectPath(nwMinimal)
|
theProject.setProjectPath(fncDir)
|
||||||
assert theProject._writeLockFile()
|
assert theProject._writeLockFile()
|
||||||
assert theProject.openProject(nwMinimal) is False
|
assert theProject.openProject(fncDir) is False
|
||||||
|
|
||||||
# Fail to read lockfile (which still opens the project)
|
# Fail to read lockfile (which still opens the project)
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("builtins.open", causeOSError)
|
mp.setattr("builtins.open", causeOSError)
|
||||||
assert theProject.openProject(nwMinimal) is True
|
caplog.clear()
|
||||||
|
assert theProject.openProject(fncDir) is True
|
||||||
|
assert "Failed to check lock file" in caplog.text
|
||||||
assert theProject.closeProject()
|
assert theProject.closeProject()
|
||||||
|
|
||||||
# Force open with lockfile
|
# Force open with lockfile
|
||||||
theProject.setProjectPath(nwMinimal)
|
theProject.setProjectPath(fncDir)
|
||||||
assert theProject._writeLockFile()
|
assert theProject._writeLockFile()
|
||||||
assert theProject.openProject(nwMinimal, overrideLock=True) is True
|
assert theProject.openProject(fncDir, overrideLock=True) is True
|
||||||
assert theProject.closeProject()
|
assert theProject.closeProject()
|
||||||
|
|
||||||
# Make a junk XML file
|
# Not a novelwriter XML file
|
||||||
oName = os.path.join(nwMinimal, nwFiles.PROJ_FILE[:-3]+"orig")
|
with monkeypatch.context() as mp:
|
||||||
bName = os.path.join(nwMinimal, nwFiles.PROJ_FILE[:-3]+"bak")
|
mp.setattr(ProjectXMLReader, "read", lambda *a: False)
|
||||||
os.rename(rName, oName)
|
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.NOT_NWX_FILE))
|
||||||
writeFile(rName, "stuff")
|
assert theProject.openProject(fncDir) is False
|
||||||
assert theProject.openProject(nwMinimal) is False
|
assert "Project file does not appear" in mockGUI.lastAlert
|
||||||
|
|
||||||
# Also write a jun XML backup file
|
# Unknown project file version
|
||||||
writeFile(bName, "stuff")
|
with monkeypatch.context() as mp:
|
||||||
assert theProject.openProject(nwMinimal) is False
|
mp.setattr(ProjectXMLReader, "read", lambda *a: False)
|
||||||
|
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.UNKNOWN_VERSION))
|
||||||
|
assert theProject.openProject(fncDir) is False
|
||||||
|
assert "Unknown or unsupported novelWriter project file" in mockGUI.lastAlert
|
||||||
|
|
||||||
# Wrong root item
|
# Other parse error
|
||||||
writeFile(rName, "<not_novelWriterXML></not_novelWriterXML>\n")
|
with monkeypatch.context() as mp:
|
||||||
assert theProject.openProject(nwMinimal) is False
|
mp.setattr(ProjectXMLReader, "read", lambda *a: False)
|
||||||
|
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.CANNOT_PARSE))
|
||||||
|
assert theProject.openProject(fncDir) is False
|
||||||
|
assert "Failed to parse project xml" in mockGUI.lastAlert
|
||||||
|
|
||||||
# Wrong file version
|
# Won't convert legacy file
|
||||||
writeFile(rName, (
|
with monkeypatch.context() as mp:
|
||||||
"<?xml version='0.0' encoding='utf-8'?>\n"
|
mp.setattr(ProjectXMLReader, "state", property(lambda *a: XMLReadState.WAS_LEGACY))
|
||||||
"<novelWriterXML "
|
mockGUI.askResponse = False
|
||||||
"appVersion=\"1.0\" "
|
assert theProject.openProject(fncDir) is False
|
||||||
"hexVersion=\"0x01000000\" "
|
assert "The file format of your project is about to be" in mockGUI.lastQuestion[1]
|
||||||
"fileVersion=\"1.0\" "
|
mockGUI.askResponse = True
|
||||||
"timeStamp=\"2020-01-01 00:00:00\">\n"
|
|
||||||
"</novelWriterXML>\n"
|
|
||||||
))
|
|
||||||
mockGUI.askResponse = False
|
|
||||||
assert theProject.openProject(nwMinimal) is False
|
|
||||||
mockGUI.undo()
|
|
||||||
|
|
||||||
# Future file version
|
# Won't convert legacy file
|
||||||
writeFile(rName, (
|
with monkeypatch.context() as mp:
|
||||||
"<?xml version='1.0' encoding='utf-8'?>\n"
|
mp.setattr(ProjectXMLReader, "hexVersion", property(lambda *a: "0x99999999"))
|
||||||
"<novelWriterXML "
|
mockGUI.askResponse = False
|
||||||
"appVersion=\"1.0\" "
|
assert theProject.openProject(fncDir) is False
|
||||||
"hexVersion=\"0x01000000\" "
|
assert "This project was saved by a newer version" in mockGUI.lastQuestion[1]
|
||||||
"fileVersion=\"99.99\" "
|
mockGUI.askResponse = True
|
||||||
"timeStamp=\"2020-01-01 00:00:00\">\n"
|
|
||||||
"</novelWriterXML>\n"
|
|
||||||
))
|
|
||||||
assert theProject.openProject(nwMinimal) is False
|
|
||||||
|
|
||||||
# Update file version
|
|
||||||
writeFile(rName, (
|
|
||||||
"<?xml version='1.0' encoding='utf-8'?>\n"
|
|
||||||
"<novelWriterXML "
|
|
||||||
"appVersion=\"1.0\" "
|
|
||||||
"hexVersion=\"0xffffffff\" "
|
|
||||||
"fileVersion=\"1.2\" "
|
|
||||||
"timeStamp=\"2020-01-01 00:00:00\">\n"
|
|
||||||
"</novelWriterXML>\n"
|
|
||||||
))
|
|
||||||
mockGUI.askResponse = False
|
|
||||||
assert theProject.openProject(nwMinimal) is False
|
|
||||||
assert mockGUI.lastQuestion[0] == "File Version"
|
|
||||||
mockGUI.undo()
|
|
||||||
|
|
||||||
# Larger hex version
|
|
||||||
writeFile(rName, (
|
|
||||||
"<?xml version='1.0' encoding='utf-8'?>\n"
|
|
||||||
"<novelWriterXML "
|
|
||||||
"appVersion=\"1.0\" "
|
|
||||||
"hexVersion=\"0xffffffff\" "
|
|
||||||
"fileVersion=\"%s\" "
|
|
||||||
"timeStamp=\"2020-01-01 00:00:00\">\n"
|
|
||||||
"</novelWriterXML>\n"
|
|
||||||
) % theProject.FILE_VERSION)
|
|
||||||
mockGUI.askResponse = False
|
|
||||||
assert theProject.openProject(nwMinimal) is False
|
|
||||||
assert mockGUI.lastQuestion[0] == "Version Conflict"
|
|
||||||
mockGUI.undo()
|
|
||||||
|
|
||||||
# Test skipping XML entries
|
|
||||||
writeFile(rName, (
|
|
||||||
"<?xml version='1.0' encoding='utf-8'?>\n"
|
|
||||||
"<novelWriterXML "
|
|
||||||
"appVersion=\"1.0\" "
|
|
||||||
"hexVersion=\"0x01000000\" "
|
|
||||||
"fileVersion=\"1.2\" "
|
|
||||||
"timeStamp=\"2020-01-01 00:00:00\">\n"
|
|
||||||
"<project><stuff/></project>\n"
|
|
||||||
"<settings><stuff/></settings>\n"
|
|
||||||
"</novelWriterXML>\n"
|
|
||||||
))
|
|
||||||
assert theProject.openProject(nwMinimal) is True
|
|
||||||
assert theProject.closeProject()
|
|
||||||
|
|
||||||
# Clean up XML files
|
|
||||||
os.unlink(rName)
|
|
||||||
os.unlink(bName)
|
|
||||||
os.rename(oName, rName)
|
|
||||||
|
|
||||||
# Add some legacy stuff that cannot be removed
|
# Add some legacy stuff that cannot be removed
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr(theProject, "_legacyDataFolder", causeOSError)
|
mp.setattr(theProject, "_legacyDataFolder", causeOSError)
|
||||||
os.mkdir(os.path.join(nwMinimal, "data_0"))
|
os.mkdir(os.path.join(fncDir, "data_0"))
|
||||||
writeFile(os.path.join(nwMinimal, "data_0", "123456789abc_main.nwd"), "stuff")
|
writeFile(os.path.join(fncDir, "data_0", "123456789abc_main.nwd"), "stuff")
|
||||||
writeFile(os.path.join(nwMinimal, "data_0", "123456789abc_main.bak"), "stuff")
|
writeFile(os.path.join(fncDir, "data_0", "123456789abc_main.bak"), "stuff")
|
||||||
mockGUI.clear()
|
mockGUI.clear()
|
||||||
assert theProject.openProject(nwMinimal) is True
|
assert theProject.openProject(fncDir) is True
|
||||||
assert "There was an error updating the project." in mockGUI.lastAlert
|
assert "There was an error updating the project." in mockGUI.lastAlert
|
||||||
|
|
||||||
assert theProject.closeProject()
|
assert theProject.closeProject()
|
||||||
@@ -522,57 +474,31 @@ def testCoreProject_Open(monkeypatch, nwMinimal, mockGUI):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
@pytest.mark.skip
|
def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncDir, refDir):
|
||||||
def testCoreProject_Save(monkeypatch, nwMinimal, mockGUI, refDir):
|
|
||||||
"""Test saving a project.
|
"""Test saving a project.
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
testFile = os.path.join(nwMinimal, "nwProject.nwx")
|
|
||||||
backFile = os.path.join(nwMinimal, "nwProject.bak")
|
|
||||||
compFile = os.path.join(refDir, os.path.pardir, "minimal", "nwProject.nwx")
|
|
||||||
|
|
||||||
# Nothing to save
|
# Nothing to save
|
||||||
assert theProject.saveProject() is False
|
assert theProject.saveProject() is False
|
||||||
|
|
||||||
# Open test project
|
mockRnd.reset()
|
||||||
assert theProject.openProject(nwMinimal)
|
buildTestProject(theProject, fncDir)
|
||||||
|
|
||||||
# Fail on folder structure check
|
# Fail on folder structure check
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("os.path.isdir", lambda *a: False)
|
mp.setattr("os.mkdir", causeOSError)
|
||||||
|
shutil.rmtree(os.path.join(fncDir, "meta"))
|
||||||
assert theProject.saveProject() is False
|
assert theProject.saveProject() is False
|
||||||
|
|
||||||
# Fail on open file
|
# Fail writing
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("builtins.open", causeOSError)
|
mp.setattr(ProjectXMLWriter, "write", lambda *a: False)
|
||||||
assert theProject.saveProject() is False
|
assert theProject.saveProject() is False
|
||||||
|
|
||||||
# Fail on creating .bak file
|
# Save with and without autosave
|
||||||
with monkeypatch.context() as mp:
|
assert theProject.saveProject(autoSave=False) is True
|
||||||
mp.setattr("os.replace", causeOSError)
|
|
||||||
assert theProject.saveProject() is False
|
|
||||||
assert os.path.isfile(backFile) is False
|
|
||||||
|
|
||||||
# Successful save
|
|
||||||
saveCount = theProject.data.saveCount
|
|
||||||
autoCount = theProject.data.autoCount
|
|
||||||
assert theProject.saveProject() is True
|
|
||||||
assert theProject.data.saveCount == saveCount + 1
|
|
||||||
assert theProject.data.autoCount == autoCount
|
|
||||||
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
|
|
||||||
|
|
||||||
# Check that a second save creates a .bak file
|
|
||||||
assert os.path.isfile(backFile) is True
|
|
||||||
|
|
||||||
# Successful autosave
|
|
||||||
saveCount = theProject.data.saveCount
|
|
||||||
autoCount = theProject.data.autoCount
|
|
||||||
assert theProject.saveProject(autoSave=True) is True
|
assert theProject.saveProject(autoSave=True) is True
|
||||||
assert theProject.data.saveCount == saveCount
|
|
||||||
assert theProject.data.autoCount == autoCount + 1
|
|
||||||
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
|
|
||||||
|
|
||||||
# Close test project
|
|
||||||
assert theProject.closeProject()
|
assert theProject.closeProject()
|
||||||
|
|
||||||
# END Test testCoreProject_Save
|
# END Test testCoreProject_Save
|
||||||
@@ -683,11 +609,11 @@ def testCoreProject_Helpers(monkeypatch, fncDir, mockGUI):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreProject_AccessItems(nwMinimal, mockGUI):
|
def testCoreProject_AccessItems(mockGUI, fncDir, mockRnd):
|
||||||
"""Test helper functions for the project folder.
|
"""Test helper functions for the project folder.
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
theProject.openProject(nwMinimal)
|
buildTestProject(theProject, fncDir)
|
||||||
|
|
||||||
# Storage Objects
|
# Storage Objects
|
||||||
assert isinstance(theProject.index, NWIndex)
|
assert isinstance(theProject.index, NWIndex)
|
||||||
@@ -696,34 +622,34 @@ def testCoreProject_AccessItems(nwMinimal, mockGUI):
|
|||||||
|
|
||||||
# Move Novel ROOT to after its files
|
# Move Novel ROOT to after its files
|
||||||
oldOrder = [
|
oldOrder = [
|
||||||
"a508bb932959c", # ROOT: Novel
|
C.hNovelRoot,
|
||||||
"a35baf2e93843", # FILE: Title Page
|
C.hPlotRoot,
|
||||||
"a6d311a93600a", # FOLDER: New Chapter
|
C.hCharRoot,
|
||||||
"f5ab3e30151e1", # FILE: New Chapter
|
C.hWorldRoot,
|
||||||
"8c659a11cd429", # FILE: New Scene
|
C.hTitlePage,
|
||||||
"7695ce551d265", # ROOT: Plot
|
C.hChapterDir,
|
||||||
"afb3043c7b2b3", # ROOT: Characters
|
C.hChapterDoc,
|
||||||
"9d5247ab588e0", # ROOT: World
|
C.hSceneDoc,
|
||||||
]
|
]
|
||||||
newOrder = [
|
newOrder = [
|
||||||
"a35baf2e93843", # FILE: Title Page
|
C.hTitlePage,
|
||||||
"f5ab3e30151e1", # FILE: New Chapter
|
C.hChapterDoc,
|
||||||
"8c659a11cd429", # FILE: New Scene
|
C.hSceneDoc,
|
||||||
"a6d311a93600a", # FOLDER: New Chapter
|
C.hChapterDir,
|
||||||
"a508bb932959c", # ROOT: Novel
|
C.hNovelRoot,
|
||||||
"7695ce551d265", # ROOT: Plot
|
C.hPlotRoot,
|
||||||
"afb3043c7b2b3", # ROOT: Characters
|
C.hCharRoot,
|
||||||
"9d5247ab588e0", # ROOT: World
|
C.hWorldRoot,
|
||||||
]
|
]
|
||||||
assert theProject.tree.handles() == oldOrder
|
assert theProject.tree.handles() == oldOrder
|
||||||
assert theProject.setTreeOrder(newOrder)
|
assert theProject.setTreeOrder(newOrder)
|
||||||
assert theProject.tree.handles() == newOrder
|
assert theProject.tree.handles() == newOrder
|
||||||
|
|
||||||
# Add a non-existing item
|
# Add a non-existing item
|
||||||
theProject.tree._treeOrder.append("01234567789abc")
|
theProject.tree._treeOrder.append(C.hInvalid)
|
||||||
|
|
||||||
# Add an item with a non-existent parent
|
# Add an item with a non-existent parent
|
||||||
nHandle = theProject.newFile("Test File", "a6d311a93600a")
|
nHandle = theProject.newFile("Test File", C.hChapterDir)
|
||||||
theProject.tree[nHandle].setParent("cba9876543210")
|
theProject.tree[nHandle].setParent("cba9876543210")
|
||||||
assert theProject.tree[nHandle].itemParent == "cba9876543210"
|
assert theProject.tree[nHandle].itemParent == "cba9876543210"
|
||||||
|
|
||||||
@@ -732,15 +658,15 @@ def testCoreProject_AccessItems(nwMinimal, mockGUI):
|
|||||||
retOrder.append(tItem.itemHandle)
|
retOrder.append(tItem.itemHandle)
|
||||||
|
|
||||||
assert retOrder == [
|
assert retOrder == [
|
||||||
"a508bb932959c", # ROOT: Novel
|
C.hNovelRoot,
|
||||||
"7695ce551d265", # ROOT: Plot
|
C.hPlotRoot,
|
||||||
"afb3043c7b2b3", # ROOT: Characters
|
C.hCharRoot,
|
||||||
"9d5247ab588e0", # ROOT: World
|
C.hWorldRoot,
|
||||||
nHandle, # FILE: Test File
|
nHandle,
|
||||||
"a35baf2e93843", # FILE: Title Page
|
C.hTitlePage,
|
||||||
"a6d311a93600a", # FOLDER: New Chapter
|
C.hChapterDir,
|
||||||
"f5ab3e30151e1", # FILE: New Chapter
|
C.hChapterDoc,
|
||||||
"8c659a11cd429", # FILE: New Scene
|
C.hSceneDoc,
|
||||||
]
|
]
|
||||||
assert theProject.tree[nHandle].itemParent is None
|
assert theProject.tree[nHandle].itemParent is None
|
||||||
|
|
||||||
@@ -748,28 +674,28 @@ def testCoreProject_AccessItems(nwMinimal, mockGUI):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
@pytest.mark.skip
|
|
||||||
def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
|
def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
|
||||||
"""Test the status and importance flag handling.
|
"""Test the status and importance flag handling.
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
|
mockRnd.reset()
|
||||||
buildTestProject(theProject, fncDir)
|
buildTestProject(theProject, fncDir)
|
||||||
|
|
||||||
statusKeys = ["s000008", "s000009", "s00000a", "s00000b"]
|
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
|
||||||
importKeys = ["i00000c", "i00000d", "i00000e", "i00000f"]
|
importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
|
||||||
|
|
||||||
# Change Status
|
# Change Status
|
||||||
# =============
|
# =============
|
||||||
|
|
||||||
theProject.tree["0000000000014"].setStatus(statusKeys[3])
|
theProject.tree[C.hNovelRoot].setStatus(statusKeys[3])
|
||||||
theProject.tree["0000000000015"].setStatus(statusKeys[2])
|
theProject.tree[C.hPlotRoot].setStatus(statusKeys[2])
|
||||||
theProject.tree["0000000000016"].setStatus(statusKeys[1])
|
theProject.tree[C.hCharRoot].setStatus(statusKeys[1])
|
||||||
theProject.tree["0000000000017"].setStatus(statusKeys[3])
|
theProject.tree[C.hWorldRoot].setStatus(statusKeys[3])
|
||||||
|
|
||||||
assert theProject.tree["0000000000014"].itemStatus == statusKeys[3]
|
assert theProject.tree[C.hNovelRoot].itemStatus == statusKeys[3]
|
||||||
assert theProject.tree["0000000000015"].itemStatus == statusKeys[2]
|
assert theProject.tree[C.hPlotRoot].itemStatus == statusKeys[2]
|
||||||
assert theProject.tree["0000000000016"].itemStatus == statusKeys[1]
|
assert theProject.tree[C.hCharRoot].itemStatus == statusKeys[1]
|
||||||
assert theProject.tree["0000000000017"].itemStatus == statusKeys[3]
|
assert theProject.tree[C.hWorldRoot].itemStatus == statusKeys[3]
|
||||||
|
|
||||||
newList = [
|
newList = [
|
||||||
{"key": statusKeys[0], "name": "New", "cols": (1, 1, 1)},
|
{"key": statusKeys[0], "name": "New", "cols": (1, 1, 1)},
|
||||||
@@ -792,8 +718,8 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
|
|||||||
assert theProject.data.itemStatus.cols(statusKeys[3]) == (4, 4, 4)
|
assert theProject.data.itemStatus.cols(statusKeys[3]) == (4, 4, 4)
|
||||||
|
|
||||||
# Check the new entry
|
# Check the new entry
|
||||||
lastKey = theProject.data.itemStatus.check("s000018")
|
lastKey = theProject.data.itemStatus.check("s000010")
|
||||||
assert lastKey == "s000018"
|
assert lastKey == "s000010"
|
||||||
assert theProject.data.itemStatus.name(lastKey) == "Finished"
|
assert theProject.data.itemStatus.name(lastKey) == "Finished"
|
||||||
assert theProject.data.itemStatus.cols(lastKey) == (5, 5, 5)
|
assert theProject.data.itemStatus.cols(lastKey) == (5, 5, 5)
|
||||||
|
|
||||||
@@ -804,7 +730,7 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
|
|||||||
# Change Importance
|
# Change Importance
|
||||||
# =================
|
# =================
|
||||||
|
|
||||||
fHandle = theProject.newFile("Jane Doe", "0000000000012")
|
fHandle = theProject.newFile("Jane Doe", C.hCharRoot)
|
||||||
theProject.tree[fHandle].setImport(importKeys[3])
|
theProject.tree[fHandle].setImport(importKeys[3])
|
||||||
|
|
||||||
assert theProject.tree[fHandle].itemImport == importKeys[3]
|
assert theProject.tree[fHandle].itemImport == importKeys[3]
|
||||||
@@ -829,8 +755,8 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
|
|||||||
assert theProject.data.itemImport.cols(importKeys[3]) == (4, 4, 4)
|
assert theProject.data.itemImport.cols(importKeys[3]) == (4, 4, 4)
|
||||||
|
|
||||||
# Check the new entry
|
# Check the new entry
|
||||||
lastKey = theProject.data.itemImport.check("i00001a")
|
lastKey = theProject.data.itemImport.check("i000012")
|
||||||
assert lastKey == "i00001a"
|
assert lastKey == "i000012"
|
||||||
assert theProject.data.itemImport.name(lastKey) == "Max"
|
assert theProject.data.itemImport.name(lastKey) == "Max"
|
||||||
assert theProject.data.itemImport.cols(lastKey) == (5, 5, 5)
|
assert theProject.data.itemImport.cols(lastKey) == (5, 5, 5)
|
||||||
|
|
||||||
@@ -854,18 +780,6 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
|
|||||||
assert theProject.saveProject() is True
|
assert theProject.saveProject() is True
|
||||||
assert theProject.closeProject() is True
|
assert theProject.closeProject() is True
|
||||||
|
|
||||||
# This should restore the default status/import labels
|
|
||||||
assert theProject.openProject(fncDir) is True
|
|
||||||
assert theProject.saveProject() is True
|
|
||||||
assert theProject.data.itemStatus.name("s000023") == "New"
|
|
||||||
assert theProject.data.itemStatus.name("s000024") == "Note"
|
|
||||||
assert theProject.data.itemStatus.name("s000025") == "Draft"
|
|
||||||
assert theProject.data.itemStatus.name("s000026") == "Finished"
|
|
||||||
assert theProject.data.itemImport.name("i000027") == "New"
|
|
||||||
assert theProject.data.itemImport.name("i000028") == "Minor"
|
|
||||||
assert theProject.data.itemImport.name("i000029") == "Major"
|
|
||||||
assert theProject.data.itemImport.name("i00002a") == "Main"
|
|
||||||
|
|
||||||
# END Test testCoreProject_StatusImport
|
# END Test testCoreProject_StatusImport
|
||||||
|
|
||||||
|
|
||||||
@@ -1268,14 +1182,14 @@ def testCoreProject_LegacyData(monkeypatch, mockGUI, fncDir):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreProject_Backup(monkeypatch, mockGUI, nwMinimal, tmpDir):
|
def testCoreProject_Backup(monkeypatch, mockGUI, fncDir, tmpDir):
|
||||||
"""Test the automated backup feature of the project class. The test
|
"""Test the automated backup feature of the project class. The test
|
||||||
creates a backup of the Minimal test project, and then unzips the
|
creates a backup of the Minimal test project, and then unzips the
|
||||||
backupd file and checks that the project XML file is identical to
|
backupd file and checks that the project XML file is identical to
|
||||||
the original file.
|
the original file.
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
assert theProject.openProject(nwMinimal)
|
buildTestProject(theProject, fncDir)
|
||||||
|
|
||||||
# Test faulty settings
|
# Test faulty settings
|
||||||
|
|
||||||
@@ -1299,11 +1213,11 @@ def testCoreProject_Backup(monkeypatch, mockGUI, nwMinimal, tmpDir):
|
|||||||
assert theProject.zipIt(doNotify=False) is False
|
assert theProject.zipIt(doNotify=False) is False
|
||||||
|
|
||||||
# Same folder as project (causes infinite loop in zipping)
|
# Same folder as project (causes infinite loop in zipping)
|
||||||
theProject.mainConf.backupPath = nwMinimal
|
theProject.mainConf.backupPath = fncDir
|
||||||
assert theProject.zipIt(doNotify=False) is False
|
assert theProject.zipIt(doNotify=False) is False
|
||||||
|
|
||||||
# Subfolder of project (causes infinite loop in zipping)
|
# Subfolder of project (causes infinite loop in zipping)
|
||||||
theProject.mainConf.backupPath = os.path.join(nwMinimal, "subdir")
|
theProject.mainConf.backupPath = os.path.join(fncDir, "subdir")
|
||||||
assert theProject.zipIt(doNotify=False) is False
|
assert theProject.zipIt(doNotify=False) is False
|
||||||
|
|
||||||
# Set a valid folder
|
# Set a valid folder
|
||||||
@@ -1335,7 +1249,7 @@ def testCoreProject_Backup(monkeypatch, mockGUI, nwMinimal, tmpDir):
|
|||||||
|
|
||||||
# Check that the main project file was restored
|
# Check that the main project file was restored
|
||||||
assert cmpFiles(
|
assert cmpFiles(
|
||||||
os.path.join(nwMinimal, "nwProject.nwx"),
|
os.path.join(fncDir, "nwProject.nwx"),
|
||||||
os.path.join(tmpDir, "extract", "nwProject.nwx")
|
os.path.join(tmpDir, "extract", "nwProject.nwx")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,23 +20,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import random
|
|
||||||
|
|
||||||
from lxml import etree
|
from tools import C
|
||||||
|
|
||||||
from PyQt5.QtGui import QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
|
|
||||||
from novelwriter.core.status import NWStatus
|
from novelwriter.core.status import NWStatus
|
||||||
|
|
||||||
statusKeys = ["sa3b179", "s1c8031", "s06671a", "sbdd640"]
|
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
|
||||||
importKeys = ["i466852", "i3eb13b", "i392456", "i23b8c1"]
|
importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStatus_Internal():
|
def testCoreStatus_Internal(mockRnd):
|
||||||
"""Test all the internal functions of the NWStatus class.
|
"""Test all the internal functions of the NWStatus class.
|
||||||
"""
|
"""
|
||||||
random.seed(42)
|
|
||||||
theStatus = NWStatus(NWStatus.STATUS)
|
theStatus = NWStatus(NWStatus.STATUS)
|
||||||
theImport = NWStatus(NWStatus.IMPORT)
|
theImport = NWStatus(NWStatus.IMPORT)
|
||||||
|
|
||||||
@@ -87,10 +85,9 @@ def testCoreStatus_Internal():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStatus_Iterator():
|
def testCoreStatus_Iterator(mockRnd):
|
||||||
"""Test the iterator functions of the NWStatus class.
|
"""Test the iterator functions of the NWStatus class.
|
||||||
"""
|
"""
|
||||||
random.seed(42)
|
|
||||||
theStatus = NWStatus(NWStatus.STATUS)
|
theStatus = NWStatus(NWStatus.STATUS)
|
||||||
|
|
||||||
theStatus.write(None, "New", (100, 100, 100))
|
theStatus.write(None, "New", (100, 100, 100))
|
||||||
@@ -132,10 +129,9 @@ def testCoreStatus_Iterator():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreStatus_Entries():
|
def testCoreStatus_Entries(mockRnd):
|
||||||
"""Test all the simple setters for the NWStatus class.
|
"""Test all the simple setters for the NWStatus class.
|
||||||
"""
|
"""
|
||||||
random.seed(42)
|
|
||||||
theStatus = NWStatus(NWStatus.STATUS)
|
theStatus = NWStatus(NWStatus.STATUS)
|
||||||
|
|
||||||
# Write
|
# Write
|
||||||
@@ -300,11 +296,9 @@ def testCoreStatus_Entries():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
@pytest.mark.skip
|
def testCoreStatus_PackUnpack(mockRnd):
|
||||||
def testCoreStatus_XMLPackUnpack():
|
"""Test all the pack/unpack of the NWStatus class.
|
||||||
"""Test all the XML pack/unpack of the NWStatus class.
|
|
||||||
"""
|
"""
|
||||||
random.seed(42)
|
|
||||||
theStatus = NWStatus(NWStatus.STATUS)
|
theStatus = NWStatus(NWStatus.STATUS)
|
||||||
theStatus.write(None, "New", (100, 100, 100))
|
theStatus.write(None, "New", (100, 100, 100))
|
||||||
theStatus.write(None, "Note", (200, 50, 0))
|
theStatus.write(None, "Note", (200, 50, 0))
|
||||||
@@ -316,36 +310,59 @@ def testCoreStatus_XMLPackUnpack():
|
|||||||
for _ in range(n):
|
for _ in range(n):
|
||||||
theStatus.increment(statusKeys[i])
|
theStatus.increment(statusKeys[i])
|
||||||
|
|
||||||
nwXML = etree.Element("novelWriterXML")
|
|
||||||
|
|
||||||
# Pack
|
# Pack
|
||||||
xStatus = etree.SubElement(nwXML, "status")
|
assert list(theStatus.pack()) == [
|
||||||
theStatus.packXML(xStatus)
|
("New", {
|
||||||
assert etree.tostring(xStatus, pretty_print=False, encoding="utf-8") == (
|
"key": statusKeys[0],
|
||||||
b'<status>'
|
"count": "3",
|
||||||
b'<entry key="sa3b179" count="3" red="100" green="100" blue="100">New</entry>'
|
"red": "100",
|
||||||
b'<entry key="s1c8031" count="5" red="200" green="50" blue="0">Note</entry>'
|
"green": "100",
|
||||||
b'<entry key="s06671a" count="7" red="200" green="150" blue="0">Draft</entry>'
|
"blue": "100"
|
||||||
b'<entry key="sbdd640" count="9" red="50" green="200" blue="0">Finished</entry>'
|
}),
|
||||||
b'</status>'
|
("Note", {
|
||||||
)
|
"key": statusKeys[1],
|
||||||
|
"count": "5",
|
||||||
|
"red": "200",
|
||||||
|
"green": "50",
|
||||||
|
"blue": "0"
|
||||||
|
}),
|
||||||
|
("Draft", {
|
||||||
|
"key": statusKeys[2],
|
||||||
|
"count": "7",
|
||||||
|
"red": "200",
|
||||||
|
"green": "150",
|
||||||
|
"blue": "0"
|
||||||
|
}),
|
||||||
|
("Finished", {
|
||||||
|
"key": statusKeys[3],
|
||||||
|
"count": "9",
|
||||||
|
"red": "50",
|
||||||
|
"green": "200",
|
||||||
|
"blue": "0"
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
# Unpack
|
# Unpack
|
||||||
theStatus = NWStatus(NWStatus.STATUS)
|
theStatus = NWStatus(NWStatus.STATUS)
|
||||||
assert theStatus.unpackXML(xStatus)
|
assert theStatus.unpack({
|
||||||
|
statusKeys[0]: {"label": "New0", "colour": (100, 100, 100), "count": countTo[0]},
|
||||||
|
statusKeys[1]: {"label": "New1", "colour": (150, 150, 150), "count": countTo[1]},
|
||||||
|
statusKeys[2]: {"label": "New2", "colour": (200, 200, 200), "count": countTo[2]},
|
||||||
|
statusKeys[3]: {"label": "New3", "colour": (250, 250, 250), "count": countTo[3]},
|
||||||
|
})
|
||||||
assert len(theStatus._store) == 4
|
assert len(theStatus._store) == 4
|
||||||
assert list(theStatus._store.keys()) == statusKeys
|
assert list(theStatus._store.keys()) == statusKeys
|
||||||
assert theStatus._store[statusKeys[0]]["name"] == "New"
|
assert theStatus._store[statusKeys[0]]["name"] == "New0"
|
||||||
assert theStatus._store[statusKeys[1]]["name"] == "Note"
|
assert theStatus._store[statusKeys[1]]["name"] == "New1"
|
||||||
assert theStatus._store[statusKeys[2]]["name"] == "Draft"
|
assert theStatus._store[statusKeys[2]]["name"] == "New2"
|
||||||
assert theStatus._store[statusKeys[3]]["name"] == "Finished"
|
assert theStatus._store[statusKeys[3]]["name"] == "New3"
|
||||||
assert theStatus._store[statusKeys[0]]["cols"] == (100, 100, 100)
|
assert theStatus._store[statusKeys[0]]["cols"] == (100, 100, 100)
|
||||||
assert theStatus._store[statusKeys[1]]["cols"] == (200, 50, 0)
|
assert theStatus._store[statusKeys[1]]["cols"] == (150, 150, 150)
|
||||||
assert theStatus._store[statusKeys[2]]["cols"] == (200, 150, 0)
|
assert theStatus._store[statusKeys[2]]["cols"] == (200, 200, 200)
|
||||||
assert theStatus._store[statusKeys[3]]["cols"] == (50, 200, 0)
|
assert theStatus._store[statusKeys[3]]["cols"] == (250, 250, 250)
|
||||||
assert theStatus._store[statusKeys[0]]["count"] == countTo[0]
|
assert theStatus._store[statusKeys[0]]["count"] == countTo[0]
|
||||||
assert theStatus._store[statusKeys[1]]["count"] == countTo[1]
|
assert theStatus._store[statusKeys[1]]["count"] == countTo[1]
|
||||||
assert theStatus._store[statusKeys[2]]["count"] == countTo[2]
|
assert theStatus._store[statusKeys[2]]["count"] == countTo[2]
|
||||||
assert theStatus._store[statusKeys[3]]["count"] == countTo[3]
|
assert theStatus._store[statusKeys[3]]["count"] == countTo[3]
|
||||||
|
|
||||||
# END Test testCoreStatus_XMLPackUnpack
|
# END Test testCoreStatus_PackUnpack
|
||||||
|
|||||||
Reference in New Issue
Block a user