Merge Novel Layouts (#837)
* Merge novel layouts and simplify the Tokenizer class * Fix core tests * Delete auto-layout code * Remove no longer needed item layouts * Remove references to deleted item layouts in test * Make some minor changes to Tokenizer class and update tests * Update test reference files * Update sample project * Fix a few issues with the Tokenizer * Centre some text in the sample documents * Make some minor changes to how new projects are generated * Add support for New Page and VSpace commands to the Tokenizer * Remove Title and Page layouts and add codes for page break and vertical space * Add document layout and fix some issues in index class with new title formats * Update tests and reference files * Bump the project file version and fix a minor issue in items class * Update tests and test coverage * Clean up some warnings and issues in tests
This commit is contained in:
committed by
GitHub
parent
c6973043e6
commit
bb1a778277
@@ -79,7 +79,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, nwMinimal):
|
||||
assert readFile(docPath) == (
|
||||
"%%~name: New File\n"
|
||||
f"%%~path: a508bb932959c/{xHandle}\n"
|
||||
"%%~kind: NOVEL/SCENE\n"
|
||||
"%%~kind: NOVEL/DOCUMENT\n"
|
||||
"### Test File\n\n"
|
||||
"Text ...\n\n"
|
||||
)
|
||||
@@ -145,14 +145,14 @@ def testCoreDocument_Methods(mockGUI, nwMinimal):
|
||||
assert theName == "New Scene"
|
||||
assert theParent == "a6d311a93600a"
|
||||
assert theClass == nwItemClass.NOVEL
|
||||
assert theLayout == nwItemLayout.SCENE
|
||||
assert theLayout == nwItemLayout.DOCUMENT
|
||||
|
||||
# Add meta data garbage
|
||||
assert theDoc.writeDocument("%%~ stuff\n### Test File\n\nText ...\n\n")
|
||||
assert readFile(docPath) == (
|
||||
"%%~name: New Scene\n"
|
||||
f"%%~path: a6d311a93600a/{sHandle}\n"
|
||||
"%%~kind: NOVEL/SCENE\n"
|
||||
"%%~kind: NOVEL/DOCUMENT\n"
|
||||
"%%~ stuff\n"
|
||||
"### Test File\n\n"
|
||||
"Text ...\n\n"
|
||||
|
||||
@@ -267,7 +267,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
assert theIndex.scanText(dHandle, "Hello World!") is False
|
||||
assert theIndex.scanText(xHandle, "Hello World!") is False
|
||||
|
||||
xItem.setLayout(nwItemLayout.SCENE)
|
||||
xItem.setLayout(nwItemLayout.DOCUMENT)
|
||||
xItem.setParent(None)
|
||||
assert theIndex.scanText(xHandle, "Hello World!") is False
|
||||
|
||||
@@ -284,11 +284,15 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
assert theIndex.scanText(xHandle, "Hello World!") is False
|
||||
|
||||
# Make some usable items
|
||||
tHandle = theProject.newFile("Title", nwItemClass.NOVEL, "a508bb932959c")
|
||||
pHandle = theProject.newFile("Page", nwItemClass.NOVEL, "a508bb932959c")
|
||||
nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c")
|
||||
cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER, "afb3043c7b2b3")
|
||||
sHandle = theProject.newFile("Scene", nwItemClass.NOVEL, "a508bb932959c")
|
||||
|
||||
# Text Indexing
|
||||
# =============
|
||||
|
||||
# Index correct text
|
||||
assert theIndex.scanText(cHandle, (
|
||||
"# Jane Smith\n"
|
||||
@@ -305,7 +309,10 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
assert theIndex._tagIndex == {"Jane": [2, cHandle, "CHARACTER", "T000001"]}
|
||||
assert theIndex.getNovelData(nHandle, "T000001")["title"] == "Hello World!"
|
||||
|
||||
# Check that title sections are indexed properly
|
||||
# Title Indexing
|
||||
# ==============
|
||||
|
||||
# Document File
|
||||
assert theIndex.scanText(nHandle, (
|
||||
"# Title One\n\n"
|
||||
"% synopsis: Synopsis One.\n\n"
|
||||
@@ -322,7 +329,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
"##### Title Five\n\n" # Not interpreted as a title, the hashes are counted as a word
|
||||
"Paragraph Five.\n\n"
|
||||
))
|
||||
assert cHandle not in theIndex._refIndex
|
||||
assert nHandle not in theIndex._refIndex
|
||||
|
||||
assert theIndex._fileIndex[nHandle]["T000001"]["level"] == "H1"
|
||||
assert theIndex._fileIndex[nHandle]["T000007"]["level"] == "H2"
|
||||
@@ -334,10 +341,10 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
assert theIndex._fileIndex[nHandle]["T000013"]["title"] == "Title Three"
|
||||
assert theIndex._fileIndex[nHandle]["T000019"]["title"] == "Title Four"
|
||||
|
||||
assert theIndex._fileIndex[nHandle]["T000001"]["layout"] == "SCENE"
|
||||
assert theIndex._fileIndex[nHandle]["T000007"]["layout"] == "SCENE"
|
||||
assert theIndex._fileIndex[nHandle]["T000013"]["layout"] == "SCENE"
|
||||
assert theIndex._fileIndex[nHandle]["T000019"]["layout"] == "SCENE"
|
||||
assert theIndex._fileIndex[nHandle]["T000001"]["layout"] == "DOCUMENT"
|
||||
assert theIndex._fileIndex[nHandle]["T000007"]["layout"] == "DOCUMENT"
|
||||
assert theIndex._fileIndex[nHandle]["T000013"]["layout"] == "DOCUMENT"
|
||||
assert theIndex._fileIndex[nHandle]["T000019"]["layout"] == "DOCUMENT"
|
||||
|
||||
assert theIndex._fileIndex[nHandle]["T000001"]["cCount"] == 23
|
||||
assert theIndex._fileIndex[nHandle]["T000007"]["cCount"] == 23
|
||||
@@ -359,6 +366,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
assert theIndex._fileIndex[nHandle]["T000013"]["synopsis"] == "Synopsis Three."
|
||||
assert theIndex._fileIndex[nHandle]["T000019"]["synopsis"] == "Synopsis Four."
|
||||
|
||||
# Note File
|
||||
assert theIndex.scanText(cHandle, (
|
||||
"# Title One\n\n"
|
||||
"@tag: One\n\n"
|
||||
@@ -375,6 +383,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
assert theIndex._fileIndex[cHandle]["T000001"]["pCount"] == 1
|
||||
assert theIndex._fileIndex[cHandle]["T000001"]["synopsis"] == "Synopsis One."
|
||||
|
||||
# Valid and Invalid References
|
||||
assert theIndex.scanText(sHandle, (
|
||||
"# Title One\n\n"
|
||||
"@pov: One\n\n" # Valid
|
||||
@@ -387,15 +396,48 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI):
|
||||
[[3, "@pov", "One"], [5, "@char", "Two"]]
|
||||
)
|
||||
|
||||
# Special Titles
|
||||
# ==============
|
||||
|
||||
assert theIndex.scanText(tHandle, (
|
||||
"#! My Project\n\n"
|
||||
">> By Jane Doe <<\n\n"
|
||||
))
|
||||
assert tHandle not in theIndex._refIndex
|
||||
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["level"] == "H1"
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["title"] == "My Project"
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["layout"] == "DOCUMENT"
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["cCount"] == 21
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["wCount"] == 5
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["pCount"] == 1
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["synopsis"] == ""
|
||||
|
||||
assert theIndex.scanText(tHandle, (
|
||||
"##! Prologue\n\n"
|
||||
"In the beginning there was time ...\n\n"
|
||||
))
|
||||
assert tHandle not in theIndex._refIndex
|
||||
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["level"] == "H2"
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["title"] == "Prologue"
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["layout"] == "DOCUMENT"
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["cCount"] == 43
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["wCount"] == 8
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["pCount"] == 1
|
||||
assert theIndex._fileIndex[tHandle]["T000001"]["synopsis"] == ""
|
||||
|
||||
# Page wo/Title
|
||||
theProject.projTree[pHandle].itemLayout = nwItemLayout.PAGE
|
||||
# =============
|
||||
|
||||
theProject.projTree[pHandle].itemLayout = nwItemLayout.DOCUMENT
|
||||
assert theIndex.scanText(pHandle, (
|
||||
"This is a page with some text on it.\n\n"
|
||||
))
|
||||
assert pHandle in theIndex._fileIndex
|
||||
assert theIndex._fileIndex[pHandle]["T000000"]["level"] == "H0"
|
||||
assert theIndex._fileIndex[pHandle]["T000000"]["title"] == ""
|
||||
assert theIndex._fileIndex[pHandle]["T000000"]["layout"] == "PAGE"
|
||||
assert theIndex._fileIndex[pHandle]["T000000"]["layout"] == "DOCUMENT"
|
||||
assert theIndex._fileIndex[pHandle]["T000000"]["cCount"] == 36
|
||||
assert theIndex._fileIndex[pHandle]["T000000"]["wCount"] == 9
|
||||
assert theIndex._fileIndex[pHandle]["T000000"]["pCount"] == 1
|
||||
@@ -587,9 +629,9 @@ def testCoreIndex_ExtractData(nwMinimal, mockGUI):
|
||||
sHandle = theProject.newFile("Scene One", nwItemClass.NOVEL, "a508bb932959c")
|
||||
tHandle = theProject.newFile("Scene Two", nwItemClass.NOVEL, "a508bb932959c")
|
||||
|
||||
theProject.projTree[hHandle].itemLayout == nwItemLayout.CHAPTER
|
||||
theProject.projTree[sHandle].itemLayout == nwItemLayout.SCENE
|
||||
theProject.projTree[tHandle].itemLayout == nwItemLayout.SCENE
|
||||
theProject.projTree[hHandle].itemLayout == nwItemLayout.DOCUMENT
|
||||
theProject.projTree[sHandle].itemLayout == nwItemLayout.DOCUMENT
|
||||
theProject.projTree[tHandle].itemLayout == nwItemLayout.DOCUMENT
|
||||
|
||||
assert theIndex.scanText(hHandle, "## Chapter One\n\n")
|
||||
assert theIndex.scanText(sHandle, "### Scene One\n\n")
|
||||
@@ -797,8 +839,8 @@ def testCoreIndex_CheckRefIndex(mockGUI):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"""Test the novel and note index checkers.
|
||||
def testCoreIndex_CheckFileIndex(mockGUI):
|
||||
"""Test the file index checker.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theIndex = NWIndex(theProject)
|
||||
@@ -809,7 +851,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -826,7 +868,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -843,7 +885,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"INVALID": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -860,7 +902,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -881,7 +923,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"stuff": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -898,7 +940,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"stuff": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -915,7 +957,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"stuff": "TITLE",
|
||||
"stuff": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -932,7 +974,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"stuff": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -949,7 +991,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"stuff": 15,
|
||||
"pCount": 2,
|
||||
@@ -966,7 +1008,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"stuff": 2,
|
||||
@@ -983,7 +1025,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -1003,7 +1045,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "XX",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -1020,7 +1062,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": 12345678,
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -1054,7 +1096,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": "72",
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -1071,7 +1113,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": "15",
|
||||
"pCount": 2,
|
||||
@@ -1088,7 +1130,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": "2",
|
||||
@@ -1105,7 +1147,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "My Novel",
|
||||
"layout": "TITLE",
|
||||
"layout": "DOCUMENT",
|
||||
"cCount": 72,
|
||||
"wCount": 15,
|
||||
"pCount": 2,
|
||||
@@ -1116,7 +1158,7 @@ def testCoreIndex_CheckNovelNoteIndex(mockGUI):
|
||||
with pytest.raises(ValueError):
|
||||
theIndex._checkFileIndex()
|
||||
|
||||
# END Test testCoreIndex_CheckNovelNoteIndex
|
||||
# END Test testCoreIndex_CheckFileIndex
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
@@ -1235,4 +1277,20 @@ def testCoreIndex_CountWords():
|
||||
assert wC == 9
|
||||
assert pC == 4
|
||||
|
||||
# Formatting Codes
|
||||
cC, wC, pC = countWords((
|
||||
"Some text\n\n"
|
||||
"[NEWPAGE]\n\n"
|
||||
"more text\n\n"
|
||||
"[NEW PAGE]]\n\n"
|
||||
"even more text\n\n"
|
||||
"[VSPACE]\n\n"
|
||||
"and some final text\n\n"
|
||||
"[VSPACE:4]\n\n"
|
||||
"THE END\n\n"
|
||||
))
|
||||
assert cC == 58
|
||||
assert wC == 13
|
||||
assert pC == 5
|
||||
|
||||
# END Test testCoreIndex_CountWords
|
||||
|
||||
@@ -73,7 +73,7 @@ def testCoreItem_Setters(mockGUI):
|
||||
theItem.setOrder(1)
|
||||
assert theItem.itemOrder == 1
|
||||
|
||||
# Status
|
||||
# Importance
|
||||
theItem.setStatus("Nonsense")
|
||||
assert theItem.itemStatus == "New"
|
||||
theItem.setStatus("New")
|
||||
@@ -85,7 +85,7 @@ def testCoreItem_Setters(mockGUI):
|
||||
theItem.setStatus("Main")
|
||||
assert theItem.itemStatus == "Main"
|
||||
|
||||
# Importance
|
||||
# Status
|
||||
theItem.itemClass = nwItemClass.NOVEL
|
||||
theItem.setStatus("Nonsense")
|
||||
assert theItem.itemStatus == "New"
|
||||
@@ -244,29 +244,37 @@ def testCoreItem_LayoutSetter(mockGUI):
|
||||
theProject = NWProject(mockGUI)
|
||||
theItem = NWItem(theProject)
|
||||
|
||||
# Layout
|
||||
# Faulty Layouts
|
||||
theItem.setLayout(None)
|
||||
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||
theItem.setLayout("NONSENSE")
|
||||
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||
|
||||
# Current Layouts
|
||||
theItem.setLayout("NO_LAYOUT")
|
||||
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||
theItem.setLayout("TITLE")
|
||||
assert theItem.itemLayout == nwItemLayout.TITLE
|
||||
theItem.setLayout("BOOK")
|
||||
assert theItem.itemLayout == nwItemLayout.BOOK
|
||||
theItem.setLayout("PAGE")
|
||||
assert theItem.itemLayout == nwItemLayout.PAGE
|
||||
theItem.setLayout("PARTITION")
|
||||
assert theItem.itemLayout == nwItemLayout.PARTITION
|
||||
theItem.setLayout("UNNUMBERED")
|
||||
assert theItem.itemLayout == nwItemLayout.UNNUMBERED
|
||||
theItem.setLayout("CHAPTER")
|
||||
assert theItem.itemLayout == nwItemLayout.CHAPTER
|
||||
theItem.setLayout("SCENE")
|
||||
assert theItem.itemLayout == nwItemLayout.SCENE
|
||||
theItem.setLayout("DOCUMENT")
|
||||
assert theItem.itemLayout == nwItemLayout.DOCUMENT
|
||||
theItem.setLayout("NOTE")
|
||||
assert theItem.itemLayout == nwItemLayout.NOTE
|
||||
|
||||
# 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
|
||||
|
||||
# Alternatives
|
||||
theItem.setLayout(nwItemLayout.NOTE)
|
||||
assert theItem.itemLayout == nwItemLayout.NOTE
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@ def testCoreProject_Open(monkeypatch, nwMinimal, mockGUI):
|
||||
))
|
||||
assert theProject.openProject(nwMinimal) is False
|
||||
|
||||
# Larger hex version
|
||||
# Update file version
|
||||
writeFile(rName, (
|
||||
"<?xml version='1.0' encoding='utf-8'?>\n"
|
||||
"<novelWriterXML "
|
||||
@@ -410,6 +410,22 @@ def testCoreProject_Open(monkeypatch, nwMinimal, mockGUI):
|
||||
))
|
||||
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
|
||||
@@ -672,12 +688,12 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
|
||||
assert theProject.projPath == os.path.expanduser("~")
|
||||
|
||||
# Create a new folder and populate it
|
||||
projPath = os.path.join(nwMinimal, "dummy1")
|
||||
projPath = os.path.join(nwMinimal, "mock1")
|
||||
assert theProject.setProjectPath(projPath, newProject=True)
|
||||
|
||||
# Make os.mkdir fail
|
||||
monkeypatch.setattr("os.mkdir", causeOSError)
|
||||
projPath = os.path.join(nwMinimal, "dummy2")
|
||||
projPath = os.path.join(nwMinimal, "mock2")
|
||||
assert not theProject.setProjectPath(projPath, newProject=True)
|
||||
|
||||
# Set back
|
||||
@@ -753,6 +769,14 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
|
||||
assert theProject.projSpell == "en_GB"
|
||||
assert theProject.projChanged
|
||||
|
||||
# Project Language
|
||||
theProject.projChanged = False
|
||||
theProject.projLang = "en"
|
||||
assert theProject.setProjectLang(None) is True
|
||||
assert theProject.projLang is None
|
||||
assert theProject.setProjectLang("en_GB") is True
|
||||
assert theProject.projLang == "en_GB"
|
||||
|
||||
# Automatic outline update
|
||||
theProject.projChanged = False
|
||||
assert theProject.setAutoOutline(True)
|
||||
|
||||
@@ -51,6 +51,8 @@ def testCoreSpell_Super(monkeypatch, tmpDir):
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr("builtins.open", causeOSError)
|
||||
assert spChk._readProjectDictionary(wList) is False
|
||||
|
||||
assert spChk._readProjectDictionary(None) is False
|
||||
assert spChk._readProjectDictionary(wList) is True
|
||||
assert spChk.projectDict == wList
|
||||
|
||||
@@ -85,22 +87,24 @@ def testCoreSpell_Enchant(monkeypatch, tmpDir):
|
||||
|
||||
spChk.setLanguage("en", wList)
|
||||
assert spChk.setLanguage("", "") is None
|
||||
assert spChk.checkWord("")
|
||||
assert spChk.checkWord("") is True
|
||||
assert spChk.suggestWords("") == []
|
||||
assert spChk.listDictionaries() == []
|
||||
assert spChk.describeDict() == ("", "")
|
||||
|
||||
# Load the proper enchant package
|
||||
# Load the proper enchant package (twice)
|
||||
spChk = NWSpellEnchant()
|
||||
spChk.setLanguage("en", wList)
|
||||
spChk.setLanguage("en", wList)
|
||||
|
||||
assert spChk.checkWord("a_word")
|
||||
assert spChk.checkWord("b_word")
|
||||
assert spChk.checkWord("c_word")
|
||||
assert not spChk.checkWord("d_word")
|
||||
# Check words
|
||||
assert spChk.checkWord("a_word") is True
|
||||
assert spChk.checkWord("b_word") is True
|
||||
assert spChk.checkWord("c_word") is True
|
||||
assert spChk.checkWord("d_word") is False
|
||||
|
||||
spChk.addWord("d_word")
|
||||
assert spChk.checkWord("d_word")
|
||||
assert spChk.checkWord("d_word") is True
|
||||
|
||||
wSuggest = spChk.suggestWords("wrod")
|
||||
assert len(wSuggest) > 0
|
||||
|
||||
@@ -81,29 +81,35 @@ def testCoreToHtml_Format(mockGUI):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToHtml_Convert(mockGUI):
|
||||
"""Test the converter of the ToHtml class.
|
||||
def testCoreToHtml_ConvertFormat(mockGUI):
|
||||
"""Test the tokenizer and converter chain using the ToHtml class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
mockGUI.theIndex = NWIndex(theProject)
|
||||
theHtml = ToHtml(theProject)
|
||||
|
||||
# Export Mode
|
||||
# ===========
|
||||
# Novel Files Headers
|
||||
# ===================
|
||||
|
||||
theHtml.isNovel = True
|
||||
theHtml.isNote = False
|
||||
theHtml.isFirst = True
|
||||
|
||||
# Header 1
|
||||
theHtml.theText = "# Title\n"
|
||||
theHtml.theText = "# Partition\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h1 class='title'>Title</h1>\n"
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: center;'>Partition</h1>\n"
|
||||
)
|
||||
|
||||
# Header 2
|
||||
theHtml.theText = "## Chapter Title\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h1>Chapter Title</h1>\n"
|
||||
assert theHtml.theResult == (
|
||||
"<h1 style='page-break-before: always;'>Chapter Title</h1>\n"
|
||||
)
|
||||
|
||||
# Header 3
|
||||
theHtml.theText = "### Scene Title\n"
|
||||
@@ -117,7 +123,26 @@ def testCoreToHtml_Convert(mockGUI):
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h3>Section Title</h3>\n"
|
||||
|
||||
# Title
|
||||
theHtml.theText = "#! Title\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: center; page-break-before: always;'>Title</h1>\n"
|
||||
)
|
||||
|
||||
# Unnumbered
|
||||
theHtml.theText = "##! Prologue\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h1 style='page-break-before: always;'>Prologue</h1>\n"
|
||||
|
||||
# Note Files Headers
|
||||
# ==================
|
||||
|
||||
theHtml.isNovel = False
|
||||
theHtml.isNote = True
|
||||
theHtml.isFirst = True
|
||||
theHtml.setLinkHeaders(True)
|
||||
|
||||
# Header 1
|
||||
@@ -144,6 +169,23 @@ def testCoreToHtml_Convert(mockGUI):
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h4><a name='T000001'></a>Heading Four</h4>\n"
|
||||
|
||||
# Title
|
||||
theHtml.theText = "#! Heading One\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 style='text-align: center;'><a name='T000001'></a>Heading One</h1>\n"
|
||||
)
|
||||
|
||||
# Unnumbered
|
||||
theHtml.theText = "##! Heading Two\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h2><a name='T000001'></a>Heading Two</h2>\n"
|
||||
|
||||
# Paragraphs
|
||||
# ==========
|
||||
|
||||
# Text
|
||||
theHtml.theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
|
||||
theHtml.tokenizeText()
|
||||
@@ -223,22 +265,64 @@ def testCoreToHtml_Convert(mockGUI):
|
||||
"</p>\n"
|
||||
)
|
||||
|
||||
# Direct Tests
|
||||
# Preview Mode
|
||||
# ============
|
||||
|
||||
theHtml.setPreview(True, True)
|
||||
|
||||
# Text (HTML4)
|
||||
theHtml.theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p>Some <b>nested bold and <i>italic</i> and "
|
||||
"<span style='text-decoration: line-through;'>strikethrough</span> "
|
||||
"text</b> here</p>\n"
|
||||
)
|
||||
|
||||
# END Test testCoreToHtml_ConvertFormat
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToHtml_ConvertDirect(mockGUI):
|
||||
"""Test the converter directly using the ToHtml class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
mockGUI.theIndex = NWIndex(theProject)
|
||||
theHtml = ToHtml(theProject)
|
||||
|
||||
theHtml.isNovel = True
|
||||
theHtml.isNote = False
|
||||
theHtml.setLinkHeaders(True)
|
||||
|
||||
# Special Titles
|
||||
# ==============
|
||||
|
||||
# Title
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_TITLE, 1, "A Title", None, theHtml.A_PBB_AUT | theHtml.A_CENTRE),
|
||||
(theHtml.T_TITLE, 1, "A Title", None, theHtml.A_PBB | theHtml.A_CENTRE),
|
||||
(theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: center; page-break-before: auto;'>"
|
||||
"<h1 class='title' style='text-align: center; page-break-before: always;'>"
|
||||
"<a name='T000001'></a>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Unnumbered
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_UNNUM, 1, "Prologue", None, theHtml.A_PBB),
|
||||
(theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 style='page-break-before: always;'>"
|
||||
"<a name='T000001'></a>Prologue</h1>\n"
|
||||
)
|
||||
|
||||
# Separators
|
||||
# ==========
|
||||
|
||||
# Separator
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_SEP, 1, "* * *", None, theHtml.A_CENTRE),
|
||||
@@ -255,8 +339,8 @@ def testCoreToHtml_Convert(mockGUI):
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<p class='skip'> </p>\n"
|
||||
|
||||
# Styles
|
||||
# ======
|
||||
# Alignment
|
||||
# =========
|
||||
|
||||
theHtml.setLinkHeaders(False)
|
||||
|
||||
@@ -308,6 +392,9 @@ def testCoreToHtml_Convert(mockGUI):
|
||||
"<h1 class='title' style='text-align: justify;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Page Break
|
||||
# ==========
|
||||
|
||||
# Page Break Always
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB | theHtml.A_PBA),
|
||||
@@ -318,32 +405,30 @@ def testCoreToHtml_Convert(mockGUI):
|
||||
"style='page-break-before: always; page-break-after: always;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Page Break Auto
|
||||
# Indent
|
||||
# ======
|
||||
|
||||
# Indent Left
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB_AUT | theHtml.A_PBA_AUT),
|
||||
(theHtml.T_TEXT, 1, "Some text ...", [], theHtml.A_IND_L),
|
||||
(theHtml.T_EMPTY, 2, "", None, theHtml.A_NONE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' "
|
||||
"style='page-break-before: auto; page-break-after: auto;'>A Title</h1>\n"
|
||||
"<p style='margin-left: 40px;'>Some text ...</p>\n"
|
||||
)
|
||||
|
||||
# Preview Mode
|
||||
# ============
|
||||
|
||||
theHtml.setPreview(True, True)
|
||||
|
||||
# Text (HTML4)
|
||||
theHtml.theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
|
||||
theHtml.tokenizeText()
|
||||
# Indent Right
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_TEXT, 1, "Some text ...", [], theHtml.A_IND_R),
|
||||
(theHtml.T_EMPTY, 2, "", None, theHtml.A_NONE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p>Some <b>nested bold and <i>italic</i> and "
|
||||
"<span style='text-decoration: line-through;'>strikethrough</span> "
|
||||
"text</b> here</p>\n"
|
||||
"<p style='margin-right: 40px;'>Some text ...</p>\n"
|
||||
)
|
||||
|
||||
# END Test testCoreToHtml_Convert
|
||||
# END Test testCoreToHtml_ConvertDirect
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
@@ -352,6 +437,7 @@ def testCoreToHtml_Complex(mockGUI, fncDir):
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theHtml = ToHtml(theProject)
|
||||
theHtml.isNovel = True
|
||||
|
||||
# Build Project
|
||||
# =============
|
||||
@@ -366,13 +452,34 @@ def testCoreToHtml_Complex(mockGUI, fncDir):
|
||||
"#### A Section\n\n\tMore text in scene two.\n",
|
||||
]
|
||||
resText = [
|
||||
"<h1>My Novel</h1>\n<p><strong>By Jane Doh</strong></p>\n",
|
||||
"<h2>Chapter 1</h2>\n<p>The text of chapter one.</p>\n",
|
||||
"<h3>Scene 1</h3>\n<p>The text of scene one.</p>\n",
|
||||
"<h4>A Section</h4>\n<p>More text in scene one.</p>\n",
|
||||
"<h2>Chapter 2</h2>\n<p>The text of chapter two.</p>\n",
|
||||
"<h3>Scene 2</h3>\n<p>The text of scene two.</p>\n",
|
||||
"<h4>A Section</h4>\n<p>\tMore text in scene two.</p>\n",
|
||||
(
|
||||
"<h1 class='title' style='text-align: center;'>My Novel</h1>\n"
|
||||
"<p><strong>By Jane Doh</strong></p>\n"
|
||||
),
|
||||
(
|
||||
"<h1 style='page-break-before: always;'>Chapter 1</h1>\n"
|
||||
"<p>The text of chapter one.</p>\n"
|
||||
),
|
||||
(
|
||||
"<h2>Scene 1</h2>\n"
|
||||
"<p>The text of scene one.</p>\n"
|
||||
),
|
||||
(
|
||||
"<h3>A Section</h3>\n"
|
||||
"<p>More text in scene one.</p>\n"
|
||||
),
|
||||
(
|
||||
"<h1 style='page-break-before: always;'>Chapter 2</h1>\n"
|
||||
"<p>The text of chapter two.</p>\n"
|
||||
),
|
||||
(
|
||||
"<h2>Scene 2</h2>\n"
|
||||
"<p>The text of scene two.</p>\n"
|
||||
),
|
||||
(
|
||||
"<h3>A Section</h3>\n"
|
||||
"<p>\tMore text in scene two.</p>\n"
|
||||
),
|
||||
]
|
||||
|
||||
for i in range(len(docText)):
|
||||
@@ -385,7 +492,7 @@ def testCoreToHtml_Complex(mockGUI, fncDir):
|
||||
assert theHtml.fullHTML == resText
|
||||
|
||||
theHtml.replaceTabs(nSpaces=2, spaceChar=" ")
|
||||
resText[6] = "<h4>A Section</h4>\n<p> More text in scene two.</p>\n"
|
||||
resText[6] = "<h3>A Section</h3>\n<p> More text in scene two.</p>\n"
|
||||
|
||||
# Check File
|
||||
# ==========
|
||||
|
||||
@@ -45,6 +45,7 @@ def testCoreToken_Setters(mockGUI):
|
||||
assert theToken.textSize == 11
|
||||
assert theToken.textFixed is False
|
||||
assert theToken.lineHeight == 1.15
|
||||
assert theToken.blockIndent == 4.0
|
||||
assert theToken.doJustify is False
|
||||
assert theToken.marginTitle == (1.000, 0.500)
|
||||
assert theToken.marginHead1 == (1.000, 0.500)
|
||||
@@ -68,7 +69,8 @@ def testCoreToken_Setters(mockGUI):
|
||||
theToken.setSceneFormat("S: %title%", True)
|
||||
theToken.setSectionFormat("X: %title%", True)
|
||||
theToken.setFont("Monospace", 10, True)
|
||||
theToken.setLineHeight(2)
|
||||
theToken.setLineHeight(2.0)
|
||||
theToken.setBlockIndent(6.0)
|
||||
theToken.setJustify(True)
|
||||
theToken.setTitleMargins(2.0, 2.0)
|
||||
theToken.setHead1Margins(2.0, 2.0)
|
||||
@@ -93,6 +95,7 @@ def testCoreToken_Setters(mockGUI):
|
||||
assert theToken.textSize == 10
|
||||
assert theToken.textFixed is True
|
||||
assert theToken.lineHeight == 2.0
|
||||
assert theToken.blockIndent == 6.0
|
||||
assert theToken.doJustify is True
|
||||
assert theToken.marginTitle == (2.0, 2.0)
|
||||
assert theToken.marginHead1 == (2.0, 2.0)
|
||||
@@ -109,6 +112,17 @@ def testCoreToken_Setters(mockGUI):
|
||||
assert theToken.doComments is True
|
||||
assert theToken.doKeywords is True
|
||||
|
||||
# Check Limits
|
||||
theToken.setLineHeight(0.0)
|
||||
assert theToken.lineHeight == 0.5
|
||||
theToken.setLineHeight(10.0)
|
||||
assert theToken.lineHeight == 5.0
|
||||
|
||||
theToken.setBlockIndent(-6.0)
|
||||
assert theToken.blockIndent == 0.0
|
||||
theToken.setBlockIndent(60.0)
|
||||
assert theToken.blockIndent == 10.0
|
||||
|
||||
# END Test testCoreToken_Setters
|
||||
|
||||
|
||||
@@ -145,13 +159,25 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, mockGUI):
|
||||
|
||||
assert theProject.saveProject()
|
||||
|
||||
# Root heading
|
||||
# Root Heading
|
||||
assert theToken.addRootHeading("stuff") is False
|
||||
assert theToken.addRootHeading(sHandle) is False
|
||||
|
||||
# First Page
|
||||
assert theToken.addRootHeading("7695ce551d265") is True
|
||||
assert theToken.theMarkdown[-1] == "# Notes: Plot\n\n"
|
||||
assert theToken.theTokens[-1] == (
|
||||
Tokenizer.T_TITLE, 0, "Notes: Plot", None, Tokenizer.A_CENTRE
|
||||
)
|
||||
|
||||
# Set text
|
||||
# Not First Page
|
||||
assert theToken.addRootHeading("7695ce551d265") is True
|
||||
assert theToken.theMarkdown[-1] == "# Notes: Plot\n\n"
|
||||
assert theToken.theTokens[-1] == (
|
||||
Tokenizer.T_TITLE, 0, "Notes: Plot", None, Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
)
|
||||
|
||||
# Set Text
|
||||
assert theToken.setText("stuff") is False
|
||||
assert theToken.setText(sHandle) is True
|
||||
assert theToken.theText == docText
|
||||
@@ -168,15 +194,8 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, mockGUI):
|
||||
assert theToken.theText == docText
|
||||
|
||||
assert theToken.isNone is False
|
||||
assert theToken.isTitle is False
|
||||
assert theToken.isBook is False
|
||||
assert theToken.isPage is False
|
||||
assert theToken.isPart is False
|
||||
assert theToken.isUnNum is False
|
||||
assert theToken.isChap is False
|
||||
assert theToken.isScene is True
|
||||
assert theToken.isNote is False
|
||||
assert theToken.isNovel is True
|
||||
assert theToken.isNote is False
|
||||
|
||||
# Pre Processing
|
||||
theToken.doPreProcessing()
|
||||
@@ -190,39 +209,115 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, mockGUI):
|
||||
# Save File
|
||||
savePath = os.path.join(nwMinimal, "dump.nwd")
|
||||
theToken.saveRawMarkdown(savePath)
|
||||
assert readFile(savePath) == "# Notes: Plot\n\n"
|
||||
assert readFile(savePath) == (
|
||||
"# Notes: Plot\n\n"
|
||||
"# Notes: Plot\n\n"
|
||||
)
|
||||
|
||||
# END Test testCoreToken_TextOps
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_Tokenize(mockGUI):
|
||||
"""Test the tokenization of the Tokenizer class.
|
||||
def testCoreToken_HeaderFormat(mockGUI):
|
||||
"""Test the tokenization of header formats in the Tokenizer class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theToken = Tokenizer(theProject)
|
||||
theToken.setKeepMarkdown(True)
|
||||
|
||||
# Header 1
|
||||
theToken.theText = "# Novel Title\n"
|
||||
# Title
|
||||
# =====
|
||||
|
||||
# Story File
|
||||
theToken.isNovel = True
|
||||
theToken.isNote = False
|
||||
theToken.isFirst = True
|
||||
theToken.theText = "#! Novel Title\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Novel Title", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TITLE, 1, "Novel Title", None, Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "#! Novel Title\n\n"
|
||||
|
||||
# Note File
|
||||
theToken.isNovel = False
|
||||
theToken.isNote = True
|
||||
theToken.isFirst = True
|
||||
theToken.theText = "#! Note Title\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Note Title", None, Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "#! Note Title\n\n"
|
||||
|
||||
# Header 1
|
||||
# ========
|
||||
|
||||
# Story File
|
||||
theToken.isNovel = True
|
||||
theToken.isNote = False
|
||||
theToken.isFirst = True
|
||||
theToken.theText = "# Novel Title\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Novel Title", None, Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "# Novel Title\n\n"
|
||||
|
||||
# Header 2
|
||||
theToken.theText = "## Chapter One\n"
|
||||
# Note File
|
||||
theToken.isNovel = False
|
||||
theToken.isNote = True
|
||||
theToken.isFirst = True
|
||||
theToken.theText = "# Note Title\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "Chapter One", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_HEAD1, 1, "Note Title", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "# Note Title\n\n"
|
||||
|
||||
# Header 2
|
||||
# ========
|
||||
|
||||
# Story File
|
||||
theToken.isNovel = True
|
||||
theToken.isNote = False
|
||||
theToken.theText = "## Chapter One\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "Chapter One", None, Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "## Chapter One\n\n"
|
||||
|
||||
# Note File
|
||||
theToken.isNovel = False
|
||||
theToken.isNote = True
|
||||
theToken.theText = "## Heading 2\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "Heading 2", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "## Heading 2\n\n"
|
||||
|
||||
# Header 3
|
||||
# ========
|
||||
|
||||
# Story File
|
||||
theToken.isNovel = True
|
||||
theToken.isNote = False
|
||||
theToken.theText = "### Scene One\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD3, 1, "Scene One", None, Tokenizer.A_NONE),
|
||||
@@ -230,8 +325,26 @@ def testCoreToken_Tokenize(mockGUI):
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "### Scene One\n\n"
|
||||
|
||||
# Note File
|
||||
theToken.isNovel = False
|
||||
theToken.isNote = True
|
||||
theToken.theText = "### Heading 3\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD3, 1, "Heading 3", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "### Heading 3\n\n"
|
||||
|
||||
# Header 4
|
||||
# ========
|
||||
|
||||
# Story File
|
||||
theToken.isNovel = True
|
||||
theToken.isNote = False
|
||||
theToken.theText = "#### A Section\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD4, 1, "A Section", None, Tokenizer.A_NONE),
|
||||
@@ -239,6 +352,83 @@ def testCoreToken_Tokenize(mockGUI):
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "#### A Section\n\n"
|
||||
|
||||
# Note File
|
||||
theToken.isNovel = False
|
||||
theToken.isNote = True
|
||||
theToken.theText = "#### Heading 4\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD4, 1, "Heading 4", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "#### Heading 4\n\n"
|
||||
|
||||
# Title
|
||||
# =====
|
||||
|
||||
# Story File
|
||||
theToken.isNovel = True
|
||||
theToken.isNote = False
|
||||
theToken.theText = "#! Title\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_TITLE, 1, "Title", None, Tokenizer.A_CENTRE | Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "#! Title\n\n"
|
||||
|
||||
# Note File
|
||||
theToken.isNovel = False
|
||||
theToken.isNote = True
|
||||
theToken.theText = "#! Title\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title", None, Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "#! Title\n\n"
|
||||
|
||||
# Unnumbered
|
||||
# ==========
|
||||
|
||||
# Story File
|
||||
theToken.isNovel = True
|
||||
theToken.isNote = False
|
||||
theToken.theText = "##! Prologue\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_UNNUM, 1, "Prologue", None, Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "##! Prologue\n\n"
|
||||
|
||||
# Note File
|
||||
theToken.isNovel = False
|
||||
theToken.isNote = True
|
||||
theToken.theText = "##! Prologue\n"
|
||||
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "Prologue", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "##! Prologue\n\n"
|
||||
|
||||
# END Test testCoreToken_HeaderFormat
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_MetaFormat(mockGUI):
|
||||
"""Test the tokenization of meta formats in the Tokenizer class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theToken = Tokenizer(theProject)
|
||||
theToken.setKeepMarkdown(True)
|
||||
|
||||
# Comment
|
||||
theToken.theText = "% A comment\n"
|
||||
theToken.tokenizeText()
|
||||
@@ -297,6 +487,72 @@ def testCoreToken_Tokenize(mockGUI):
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n"
|
||||
|
||||
# END Test testCoreToken_MetaFormat
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_MarginFormat(mockGUI):
|
||||
"""Test the tokenization of margin formats in the Tokenizer class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theToken = Tokenizer(theProject)
|
||||
theToken.setKeepMarkdown(True)
|
||||
|
||||
# Alignment and Indentation
|
||||
dblIndent = Tokenizer.A_IND_L | Tokenizer.A_IND_R
|
||||
rIndAlign = Tokenizer.A_RIGHT | Tokenizer.A_IND_R
|
||||
theToken.theText = (
|
||||
"Some regular text\n\n"
|
||||
"Some left-aligned text <<\n\n"
|
||||
">> Some right-aligned text\n\n"
|
||||
">> Some centered text <<\n\n"
|
||||
"> Left-indented block\n\n"
|
||||
"Right-indented block <\n\n"
|
||||
"> Double-indented block <\n\n"
|
||||
">> Right-indent, right-aligned <\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_TEXT, 1, "Some regular text", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 3, "Some left-aligned text", [], Tokenizer.A_LEFT),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some right-aligned text", [], Tokenizer.A_RIGHT),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 7, "Some centered text", [], Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 9, "Left-indented block", [], Tokenizer.A_IND_L),
|
||||
(Tokenizer.T_EMPTY, 10, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 11, "Right-indented block", [], Tokenizer.A_IND_R),
|
||||
(Tokenizer.T_EMPTY, 12, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 13, "Double-indented block", [], dblIndent),
|
||||
(Tokenizer.T_EMPTY, 14, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 15, "Right-indent, right-aligned", [], rIndAlign),
|
||||
(Tokenizer.T_EMPTY, 16, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 16, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == (
|
||||
"Some regular text\n\n"
|
||||
"Some left-aligned text\n\n"
|
||||
"Some right-aligned text\n\n"
|
||||
"Some centered text\n\n"
|
||||
"Left-indented block\n\n"
|
||||
"Right-indented block\n\n"
|
||||
"Double-indented block\n\n"
|
||||
"Right-indent, right-aligned\n\n\n"
|
||||
)
|
||||
|
||||
# END Test testCoreToken_MarginFormat
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_TextFormat(mockGUI):
|
||||
"""Test the tokenization of text formats in the Tokenizer class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theToken = Tokenizer(theProject)
|
||||
theToken.setKeepMarkdown(True)
|
||||
|
||||
# Text
|
||||
theToken.theText = "Some plain text\non two lines\n\n\n"
|
||||
theToken.tokenizeText()
|
||||
@@ -408,55 +664,214 @@ def testCoreToken_Tokenize(mockGUI):
|
||||
"Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n\n"
|
||||
)
|
||||
|
||||
# Alignment and Indentation
|
||||
dblIndent = Tokenizer.A_IND_L | Tokenizer.A_IND_R
|
||||
rIndAlign = Tokenizer.A_RIGHT | Tokenizer.A_IND_R
|
||||
theToken.theText = (
|
||||
"Some regular text\n\n"
|
||||
"Some left-aligned text <<\n\n"
|
||||
">> Some right-aligned text\n\n"
|
||||
">> Some centered text <<\n\n"
|
||||
"> Left-indented block\n\n"
|
||||
"Right-indented block <\n\n"
|
||||
"> Double-indented block <\n\n"
|
||||
">> Right-indent, right-aligned <\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_TEXT, 1, "Some regular text", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 3, "Some left-aligned text", [], Tokenizer.A_LEFT),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some right-aligned text", [], Tokenizer.A_RIGHT),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 7, "Some centered text", [], Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 9, "Left-indented block", [], Tokenizer.A_IND_L),
|
||||
(Tokenizer.T_EMPTY, 10, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 11, "Right-indented block", [], Tokenizer.A_IND_R),
|
||||
(Tokenizer.T_EMPTY, 12, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 13, "Double-indented block", [], dblIndent),
|
||||
(Tokenizer.T_EMPTY, 14, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 15, "Right-indent, right-aligned", [], rIndAlign),
|
||||
(Tokenizer.T_EMPTY, 16, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 16, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
assert theToken.theMarkdown[-1] == (
|
||||
"Some regular text\n\n"
|
||||
"Some left-aligned text\n\n"
|
||||
"Some right-aligned text\n\n"
|
||||
"Some centered text\n\n"
|
||||
"Left-indented block\n\n"
|
||||
"Right-indented block\n\n"
|
||||
"Double-indented block\n\n"
|
||||
"Right-indent, right-aligned\n\n\n"
|
||||
)
|
||||
|
||||
# END Test testCoreToken_Tokenize
|
||||
# END Test testCoreToken_TextFormat
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_Headers(mockGUI):
|
||||
def testCoreToken_SpecialFormat(mockGUI):
|
||||
"""Test the tokenization of special formats in the Tokenizer class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theToken = Tokenizer(theProject)
|
||||
|
||||
theToken.isNovel = True
|
||||
|
||||
# New Page
|
||||
# ========
|
||||
|
||||
correctResp = [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_HEAD1, 5, "Title Two", None, Tokenizer.A_CENTRE | Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Command wo/Space
|
||||
theToken.isFirst = True
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[NEWPAGE]\n\n"
|
||||
"# Title Two\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == correctResp
|
||||
|
||||
# Command w/Space
|
||||
theToken.isFirst = True
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[NEW PAGE]\n\n"
|
||||
"# Title Two\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == correctResp
|
||||
|
||||
# Trailing Spaces
|
||||
theToken.isFirst = True
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[NEW PAGE] \t\n\n"
|
||||
"# Title Two\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == correctResp
|
||||
|
||||
# Single Empty Paragraph
|
||||
# ======================
|
||||
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[VSPACE] \n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Multiple Empty Paragraphs
|
||||
# =========================
|
||||
|
||||
# One Skip
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[VSPACE:1] \n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Three Skips
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[VSPACE:3] \n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 3, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Malformed Command, Case 1
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[VSPACE:3xa] \n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Malformed Command, Case 2
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[VSPACE:3.5]\n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Malformed Command, Case 3
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[VSPACE:-1]\n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 5, "Some text to go here ...", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Empty Paragraph and Page Break
|
||||
# ==============================
|
||||
|
||||
# Single Skip
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[NEW PAGE]\n\n"
|
||||
"[VSPACE]\n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 7, "Some text to go here ...", [], 0),
|
||||
(Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# Multiple Skip
|
||||
theToken.theText = (
|
||||
"# Title One\n\n"
|
||||
"[NEW PAGE]\n\n"
|
||||
"[VSPACE:3]\n\n"
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
theToken.tokenizeText()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 4, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_PBB),
|
||||
(Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_SKIP, 5, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 6, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 7, "Some text to go here ...", [], 0),
|
||||
(Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 8, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# END Test testCoreToken_SpecialFormat
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_ProcessHeaders(mockGUI):
|
||||
"""Test the header and page parser of the Tokenizer class.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
@@ -466,31 +881,45 @@ def testCoreToken_Headers(mockGUI):
|
||||
|
||||
# Nothing
|
||||
theToken.theText = "Some text ...\n"
|
||||
assert theToken.doHeaders() is True
|
||||
assert theToken.doHeaders() is False
|
||||
theToken.isNone = True
|
||||
assert theToken.doHeaders() is False
|
||||
theToken.isNone = False
|
||||
assert theToken.doHeaders() is True
|
||||
assert theToken.doHeaders() is False
|
||||
theToken.isNote = True
|
||||
assert theToken.doHeaders() is False
|
||||
theToken.isNote = False
|
||||
|
||||
##
|
||||
# Novel
|
||||
# Story FIles
|
||||
##
|
||||
|
||||
theToken.isNone = False
|
||||
theToken.isNote = False
|
||||
theToken.isNovel = True
|
||||
|
||||
# Titles
|
||||
# ======
|
||||
|
||||
# H1: Title
|
||||
theToken.theText = "# Novel Title\n"
|
||||
# H1: Title, First Page
|
||||
assert theToken.isFirst is True
|
||||
theToken.theText = "# Part One\n"
|
||||
theToken.setTitleFormat(r"T: %title%")
|
||||
theToken.tokenizeText()
|
||||
theToken.doHeaders()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "T: Novel Title", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_HEAD1, 1, "T: Part One", None, Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# H1: Title, Not First Page
|
||||
assert theToken.isFirst is False
|
||||
theToken.theText = "# Part One\n"
|
||||
theToken.setTitleFormat(r"T: %title%")
|
||||
theToken.tokenizeText()
|
||||
theToken.doHeaders()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "T: Part One", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
@@ -508,20 +937,8 @@ def testCoreToken_Headers(mockGUI):
|
||||
]
|
||||
|
||||
# H2: Unnumbered Chapter
|
||||
theToken.theText = "## Chapter One\n"
|
||||
theToken.setUnNumberedFormat(r"U: %title%")
|
||||
theToken.isUnNum = True
|
||||
theToken.tokenizeText()
|
||||
theToken.doHeaders()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "U: Chapter One", None, Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# H2: Unnumbered Chapter with Star
|
||||
theToken.theText = "## *Prologue\n"
|
||||
theToken.setUnNumberedFormat(r"U: %title%")
|
||||
theToken.isUnNum = False
|
||||
theToken.tokenizeText()
|
||||
theToken.doHeaders()
|
||||
assert theToken.theTokens == [
|
||||
@@ -703,54 +1120,4 @@ def testCoreToken_Headers(mockGUI):
|
||||
theToken.doHeaders()
|
||||
assert theToken.firstScene is False
|
||||
|
||||
##
|
||||
# Title or Partition
|
||||
##
|
||||
|
||||
theToken.isNovel = False
|
||||
|
||||
# H1: Title
|
||||
theToken.theText = "# Novel Title\n"
|
||||
theToken.setTitleFormat(r"T: %title%")
|
||||
theToken.isTitle = True
|
||||
theToken.isPart = False
|
||||
theToken.tokenizeText()
|
||||
theToken.doHeaders()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_TITLE, 1, "Novel Title", None, Tokenizer.A_PBB_AUT | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_PBA | Tokenizer.A_CENTRE),
|
||||
]
|
||||
|
||||
# H1: Partition
|
||||
theToken.theText = "# Partition Title\n"
|
||||
theToken.setTitleFormat(r"T: %title%")
|
||||
theToken.isTitle = False
|
||||
theToken.isPart = True
|
||||
theToken.tokenizeText()
|
||||
theToken.doHeaders()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Partition Title", None, Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_PBA | Tokenizer.A_CENTRE),
|
||||
]
|
||||
|
||||
##
|
||||
# Page
|
||||
##
|
||||
|
||||
theToken.isNovel = False
|
||||
theToken.isTitle = False
|
||||
theToken.isPart = False
|
||||
theToken.isPage = True
|
||||
|
||||
# Some Page Text
|
||||
theToken.theText = "Page text\n\nMore text\n"
|
||||
theToken.tokenizeText()
|
||||
theToken.doHeaders()
|
||||
assert theToken.theTokens == [
|
||||
(Tokenizer.T_TEXT, 1, "Page text", [], Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 2, "", None, Tokenizer.A_NONE),
|
||||
(Tokenizer.T_TEXT, 3, "More text", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 3, "", None, Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# END Test testCoreToken_Headers
|
||||
# END Test testCoreToken_ProcessHeaders
|
||||
|
||||
@@ -65,7 +65,7 @@ def testCoreToOdt_Convert(mockGUI):
|
||||
theDoc.closeDocument()
|
||||
assert xmlToText(theDoc._xText) == (
|
||||
'<office:text>'
|
||||
'<text:h text:style-name="Heading_1" text:outline-level="1">Title</text:h>'
|
||||
'<text:h text:style-name="P1" text:outline-level="1">Title</text:h>'
|
||||
'</office:text>'
|
||||
)
|
||||
|
||||
@@ -77,7 +77,7 @@ def testCoreToOdt_Convert(mockGUI):
|
||||
theDoc.closeDocument()
|
||||
assert xmlToText(theDoc._xText) == (
|
||||
'<office:text>'
|
||||
'<text:h text:style-name="Heading_2" text:outline-level="2">Chapter Title</text:h>'
|
||||
'<text:h text:style-name="P2" text:outline-level="2">Chapter Title</text:h>'
|
||||
'</office:text>'
|
||||
)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ from nw.constants import nwFiles
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def dummyItems(mockGUI):
|
||||
def mockItems(mockGUI):
|
||||
"""Create a list of mock items.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
@@ -54,7 +54,7 @@ def dummyItems(mockGUI):
|
||||
itemC.itemName = "Chapter One"
|
||||
itemC.itemType = nwItemType.FILE
|
||||
itemC.itemClass = nwItemClass.NOVEL
|
||||
itemC.itemLayout = nwItemLayout.CHAPTER
|
||||
itemC.itemLayout = nwItemLayout.DOCUMENT
|
||||
itemC.charCount = 300
|
||||
itemC.wordCount = 50
|
||||
itemC.paraCount = 2
|
||||
@@ -63,7 +63,7 @@ def dummyItems(mockGUI):
|
||||
itemD.itemName = "Scene One"
|
||||
itemD.itemType = nwItemType.FILE
|
||||
itemD.itemClass = nwItemClass.NOVEL
|
||||
itemD.itemLayout = nwItemLayout.SCENE
|
||||
itemD.itemLayout = nwItemLayout.DOCUMENT
|
||||
itemD.charCount = 3000
|
||||
itemD.wordCount = 500
|
||||
itemD.paraCount = 20
|
||||
@@ -110,7 +110,7 @@ def dummyItems(mockGUI):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_BuildTree(mockGUI, dummyItems):
|
||||
def testCoreTree_BuildTree(mockGUI, mockItems):
|
||||
"""Test building a project tree from a list of items.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
@@ -128,7 +128,7 @@ def testCoreTree_BuildTree(mockGUI, dummyItems):
|
||||
assert not theTree.isTrashRoot("a000000000003")
|
||||
|
||||
aHandles = []
|
||||
for tHandle, pHandle, nwItem in dummyItems:
|
||||
for tHandle, pHandle, nwItem in mockItems:
|
||||
aHandles.append(tHandle)
|
||||
assert theTree.append(tHandle, pHandle, nwItem)
|
||||
|
||||
@@ -138,7 +138,7 @@ def testCoreTree_BuildTree(mockGUI, dummyItems):
|
||||
assert theTree
|
||||
|
||||
# Check the number of elements (calls __len__)
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
|
||||
# Check that we have the correct handles
|
||||
assert theTree.handles() == aHandles
|
||||
@@ -160,46 +160,46 @@ def testCoreTree_BuildTree(mockGUI, dummyItems):
|
||||
itemT.isExpanded = False
|
||||
|
||||
assert not theTree.append("1234567890abc", None, itemT)
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
|
||||
# Generate handle automatically
|
||||
itemT = NWItem(theProject)
|
||||
itemT.itemName = "New File"
|
||||
itemT.itemType = nwItemType.FILE
|
||||
itemT.itemClass = nwItemClass.NOVEL
|
||||
itemT.itemLayout = nwItemLayout.SCENE
|
||||
itemT.itemLayout = nwItemLayout.DOCUMENT
|
||||
|
||||
assert theTree.append(None, None, itemT)
|
||||
assert len(theTree) == len(dummyItems) + 1
|
||||
assert len(theTree) == len(mockItems) + 1
|
||||
|
||||
theList = theTree.handles()
|
||||
assert theList[-1] == "73475cb40a568"
|
||||
|
||||
# Try to add existing handle
|
||||
assert not theTree.append("73475cb40a568", None, itemT)
|
||||
assert len(theTree) == len(dummyItems) + 1
|
||||
assert len(theTree) == len(mockItems) + 1
|
||||
|
||||
# Delete a non-existing item
|
||||
del theTree["stuff"]
|
||||
assert len(theTree) == len(dummyItems) + 1
|
||||
assert len(theTree) == len(mockItems) + 1
|
||||
|
||||
# Delete the last item
|
||||
del theTree["73475cb40a568"]
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
assert "73475cb40a568" not in theTree
|
||||
|
||||
# Delete the Novel, Archive and Trash folders
|
||||
del theTree["a000000000001"]
|
||||
assert len(theTree) == len(dummyItems) - 1
|
||||
assert len(theTree) == len(mockItems) - 1
|
||||
assert "a000000000001" not in theTree
|
||||
|
||||
del theTree["a000000000002"]
|
||||
assert len(theTree) == len(dummyItems) - 2
|
||||
assert len(theTree) == len(mockItems) - 2
|
||||
assert "a000000000002" not in theTree
|
||||
assert theTree.archiveRoot() is None
|
||||
|
||||
del theTree["a000000000003"]
|
||||
assert len(theTree) == len(dummyItems) - 3
|
||||
assert len(theTree) == len(mockItems) - 3
|
||||
assert "a000000000003" not in theTree
|
||||
assert theTree.trashRoot() is None
|
||||
|
||||
@@ -207,16 +207,16 @@ def testCoreTree_BuildTree(mockGUI, dummyItems):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_Methods(mockGUI, dummyItems):
|
||||
"""Test bvarious class methods.
|
||||
def testCoreTree_Methods(mockGUI, mockItems):
|
||||
"""Test various class methods.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theTree = NWTree(theProject)
|
||||
|
||||
for tHandle, pHandle, nwItem in dummyItems:
|
||||
for tHandle, pHandle, nwItem in mockItems:
|
||||
theTree.append(tHandle, pHandle, nwItem)
|
||||
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
|
||||
# Root item lookup
|
||||
theTree._treeRoots.append("stuff")
|
||||
@@ -254,141 +254,15 @@ def testCoreTree_Methods(mockGUI, dummyItems):
|
||||
]
|
||||
|
||||
# Change file layout
|
||||
assert not theTree.setFileItemLayout("stuff", nwItemLayout.UNNUMBERED)
|
||||
assert not theTree.setFileItemLayout("b000000000001", nwItemLayout.UNNUMBERED)
|
||||
assert not theTree.setFileItemLayout("c000000000001", "stuff")
|
||||
assert theTree.setFileItemLayout("c000000000001", nwItemLayout.UNNUMBERED)
|
||||
assert theTree["c000000000001"].itemLayout == nwItemLayout.UNNUMBERED
|
||||
assert theTree.setFileItemLayout("stuff", nwItemLayout.DOCUMENT) is False
|
||||
assert theTree.setFileItemLayout("b000000000001", nwItemLayout.DOCUMENT) is False
|
||||
assert theTree.setFileItemLayout("c000000000001", "stuff") is False
|
||||
assert theTree.setFileItemLayout("c000000000001", nwItemLayout.NOTE) is True
|
||||
assert theTree["c000000000001"].itemLayout == nwItemLayout.NOTE
|
||||
|
||||
# END Test testCoreTree_Methods
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_UpdateItemLayout(mockGUI, dummyItems):
|
||||
"""Test building a project tree from a list of items.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theTree = NWTree(theProject)
|
||||
|
||||
for tHandle, pHandle, nwItem in dummyItems:
|
||||
theTree.append(tHandle, pHandle, nwItem)
|
||||
|
||||
assert len(theTree) == len(dummyItems)
|
||||
|
||||
# Check rejected items
|
||||
assert not theTree.updateItemLayout("0000000000000", "H1") # Non-existent handle
|
||||
assert not theTree.updateItemLayout("a000000000004", "H2") # Character file
|
||||
assert not theTree.updateItemLayout("c000000000002", "H0") # Wrong header level
|
||||
|
||||
cHandle = "c000000000002"
|
||||
|
||||
# Check layouts we won't change
|
||||
theTree[cHandle].setLayout(nwItemLayout.NO_LAYOUT)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H1")
|
||||
|
||||
theTree[cHandle].setLayout(nwItemLayout.TITLE)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H1")
|
||||
|
||||
theTree[cHandle].setLayout(nwItemLayout.PAGE)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H1")
|
||||
|
||||
theTree[cHandle].setLayout(nwItemLayout.NOTE)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H1")
|
||||
|
||||
# BOOK is also a layout we change to, but never from
|
||||
theTree[cHandle].setLayout(nwItemLayout.BOOK)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H1")
|
||||
|
||||
# Test SCENE Changes
|
||||
# ==================
|
||||
|
||||
# H1 -> BOOK
|
||||
theTree[cHandle].setLayout(nwItemLayout.SCENE)
|
||||
assert theTree.updateItemLayout("c000000000002", "H1")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.BOOK
|
||||
|
||||
# H2 -> CHAPTER
|
||||
theTree[cHandle].setLayout(nwItemLayout.SCENE)
|
||||
assert theTree.updateItemLayout("c000000000002", "H2")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.CHAPTER
|
||||
|
||||
# H3 -> No CHange
|
||||
theTree[cHandle].setLayout(nwItemLayout.SCENE)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H3")
|
||||
|
||||
# H4 -> No CHange
|
||||
theTree[cHandle].setLayout(nwItemLayout.SCENE)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H4")
|
||||
|
||||
# Test CHAPTER Changes
|
||||
# ====================
|
||||
|
||||
# H1 -> BOOK
|
||||
theTree[cHandle].setLayout(nwItemLayout.CHAPTER)
|
||||
assert theTree.updateItemLayout("c000000000002", "H1")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.BOOK
|
||||
|
||||
# H2 -> No Change
|
||||
theTree[cHandle].setLayout(nwItemLayout.CHAPTER)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H2")
|
||||
|
||||
# H3 -> SCENE
|
||||
theTree[cHandle].setLayout(nwItemLayout.CHAPTER)
|
||||
assert theTree.updateItemLayout("c000000000002", "H3")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.SCENE
|
||||
|
||||
# H4 -> SCENE
|
||||
theTree[cHandle].setLayout(nwItemLayout.CHAPTER)
|
||||
assert theTree.updateItemLayout("c000000000002", "H4")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.SCENE
|
||||
|
||||
# Test UNNUMBERED Changes
|
||||
# =======================
|
||||
|
||||
# H1 -> BOOK
|
||||
theTree[cHandle].setLayout(nwItemLayout.UNNUMBERED)
|
||||
assert theTree.updateItemLayout("c000000000002", "H1")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.BOOK
|
||||
|
||||
# H2 -> No Change
|
||||
theTree[cHandle].setLayout(nwItemLayout.UNNUMBERED)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H2")
|
||||
|
||||
# H3 -> SCENE
|
||||
theTree[cHandle].setLayout(nwItemLayout.UNNUMBERED)
|
||||
assert theTree.updateItemLayout("c000000000002", "H3")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.SCENE
|
||||
|
||||
# H4 -> SCENE
|
||||
theTree[cHandle].setLayout(nwItemLayout.UNNUMBERED)
|
||||
assert theTree.updateItemLayout("c000000000002", "H4")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.SCENE
|
||||
|
||||
# Test PARTITION Changes
|
||||
# ======================
|
||||
|
||||
# H1 -> BOOK
|
||||
theTree[cHandle].setLayout(nwItemLayout.PARTITION)
|
||||
assert not theTree.updateItemLayout("c000000000002", "H1")
|
||||
|
||||
# H2 -> No Change
|
||||
theTree[cHandle].setLayout(nwItemLayout.PARTITION)
|
||||
assert theTree.updateItemLayout("c000000000002", "H2")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.CHAPTER
|
||||
|
||||
# H3 -> SCENE
|
||||
theTree[cHandle].setLayout(nwItemLayout.PARTITION)
|
||||
assert theTree.updateItemLayout("c000000000002", "H3")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.SCENE
|
||||
|
||||
# H4 -> SCENE
|
||||
theTree[cHandle].setLayout(nwItemLayout.PARTITION)
|
||||
assert theTree.updateItemLayout("c000000000002", "H4")
|
||||
assert theTree[cHandle].itemLayout == nwItemLayout.SCENE
|
||||
|
||||
# END Test testCoreTree_UpdateItemLayout
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_MakeHandles(monkeypatch, mockGUI):
|
||||
"""Test generating item handles.
|
||||
@@ -433,16 +307,16 @@ def testCoreTree_MakeHandles(monkeypatch, mockGUI):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_Stats(mockGUI, dummyItems):
|
||||
def testCoreTree_Stats(mockGUI, mockItems):
|
||||
"""Test project stats methods.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theTree = NWTree(theProject)
|
||||
|
||||
for tHandle, pHandle, nwItem in dummyItems:
|
||||
for tHandle, pHandle, nwItem in mockItems:
|
||||
theTree.append(tHandle, pHandle, nwItem)
|
||||
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
theTree._treeOrder.append("stuff")
|
||||
|
||||
# Count Words
|
||||
@@ -460,18 +334,18 @@ def testCoreTree_Stats(mockGUI, dummyItems):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_Reorder(mockGUI, dummyItems):
|
||||
def testCoreTree_Reorder(mockGUI, mockItems):
|
||||
"""Test changing tree order.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theTree = NWTree(theProject)
|
||||
|
||||
aHandle = []
|
||||
for tHandle, pHandle, nwItem in dummyItems:
|
||||
for tHandle, pHandle, nwItem in mockItems:
|
||||
aHandle.append(tHandle)
|
||||
theTree.append(tHandle, pHandle, nwItem)
|
||||
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
|
||||
bHandle = aHandle.copy()
|
||||
bHandle[2], bHandle[3] = bHandle[3], bHandle[2]
|
||||
@@ -492,16 +366,16 @@ def testCoreTree_Reorder(mockGUI, dummyItems):
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_XMLPackUnpack(mockGUI, dummyItems):
|
||||
def testCoreTree_XMLPackUnpack(mockGUI, mockItems):
|
||||
"""Test packing and unpacking the tree to and from XML.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theTree = NWTree(theProject)
|
||||
|
||||
for tHandle, pHandle, nwItem in dummyItems:
|
||||
for tHandle, pHandle, nwItem in mockItems:
|
||||
theTree.append(tHandle, pHandle, nwItem)
|
||||
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
|
||||
nwXML = etree.Element("novelWriterXML")
|
||||
theTree.packXML(nwXML)
|
||||
@@ -516,11 +390,11 @@ def testCoreTree_XMLPackUnpack(mockGUI, dummyItems):
|
||||
b"<expanded>True</expanded></item>"
|
||||
b"<item handle=\"c000000000001\" order=\"0\" parent=\"b000000000001\">"
|
||||
b"<name>Chapter One</name><type>FILE</type><class>NOVEL</class><status>None</status>"
|
||||
b"<exported>True</exported><layout>CHAPTER</layout><charCount>300</charCount>"
|
||||
b"<exported>True</exported><layout>DOCUMENT</layout><charCount>300</charCount>"
|
||||
b"<wordCount>50</wordCount><paraCount>2</paraCount><cursorPos>0</cursorPos></item>"
|
||||
b"<item handle=\"c000000000002\" order=\"0\" parent=\"b000000000001\">"
|
||||
b"<name>Scene One</name><type>FILE</type><class>NOVEL</class><status>None</status>"
|
||||
b"<exported>True</exported><layout>SCENE</layout><charCount>3000</charCount>"
|
||||
b"<exported>True</exported><layout>DOCUMENT</layout><charCount>3000</charCount>"
|
||||
b"<wordCount>500</wordCount><paraCount>20</paraCount><cursorPos>0</cursorPos></item>"
|
||||
b"<item handle=\"a000000000002\" order=\"0\" parent=\"None\">"
|
||||
b"<name>Outtakes</name><type>ROOT</type><class>ARCHIVE</class><status>None</status>"
|
||||
@@ -542,22 +416,22 @@ def testCoreTree_XMLPackUnpack(mockGUI, dummyItems):
|
||||
assert len(theTree) == 0
|
||||
assert not theTree.unpackXML(nwXML)
|
||||
assert theTree.unpackXML(nwXML[0])
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
|
||||
# END Test testCoreTree_XMLPackUnpack
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreTree_ToCFile(monkeypatch, mockGUI, dummyItems, tmpDir):
|
||||
def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpDir):
|
||||
"""Test writing the ToC.txt file.
|
||||
"""
|
||||
theProject = NWProject(mockGUI)
|
||||
theTree = NWTree(theProject)
|
||||
|
||||
for tHandle, pHandle, nwItem in dummyItems:
|
||||
for tHandle, pHandle, nwItem in mockItems:
|
||||
theTree.append(tHandle, pHandle, nwItem)
|
||||
|
||||
assert len(theTree) == len(dummyItems)
|
||||
assert len(theTree) == len(mockItems)
|
||||
theTree._treeOrder.append("stuff")
|
||||
|
||||
def dummyIsFile(fileName):
|
||||
@@ -588,8 +462,8 @@ def testCoreTree_ToCFile(monkeypatch, mockGUI, dummyItems, tmpDir):
|
||||
"\n"
|
||||
"File Name Class Layout Document Label\n"
|
||||
"-------------------------------------------------------------\n"
|
||||
f"{pathA} NOVEL CHAPTER Chapter One\n"
|
||||
f"{pathB} NOVEL SCENE Scene One\n"
|
||||
f"{pathA} NOVEL DOCUMENT Chapter One\n"
|
||||
f"{pathB} NOVEL DOCUMENT Scene One\n"
|
||||
f"{pathC} CHARACTER NOTE Jane Doe\n"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user