diff --git a/tests/conftest.py b/tests/conftest.py index 7423d849..d4b10213 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,10 +5,14 @@ import sys import pytest import shutil + from os import path, mkdir +from nwdummy import DummyMain sys.path.insert(1, path.abspath(path.join(path.dirname(__file__), path.pardir))) +from nw.config import Config # noqa: E402 + @pytest.fixture(scope="session") def nwTemp(): testDir = path.dirname(__file__) @@ -19,6 +23,24 @@ def nwTemp(): mkdir(tempDir) return tempDir +@pytest.fixture(scope="session") +def nwRef(): + testDir = path.dirname(__file__) + refDir = path.join(testDir, "reference") + return refDir + +@pytest.fixture(scope="session") +def nwConf(nwRef, nwTemp): + theConf = Config() + theConf.initConfig(nwRef, nwTemp) + return theConf + +@pytest.fixture(scope="session") +def nwDummy(nwRef, nwTemp, nwConf): + theDummy = DummyMain() + theDummy.mainConf = nwConf + return theDummy + @pytest.fixture(scope="session") def nwTempProj(nwTemp): projDir = path.join(nwTemp, "proj") @@ -40,20 +62,6 @@ def nwTempBuild(nwTemp): mkdir(buildDir) return buildDir -@pytest.fixture(scope="session") -def nwTempCustom(nwTemp): - customDir = path.join(nwTemp, "custom") - if not path.isdir(customDir): - mkdir(customDir) - return customDir - -@pytest.fixture(scope="session") -def nwTempSample(nwTemp): - sampleDir = path.join(nwTemp, "sample") - if not path.isdir(sampleDir): - mkdir(sampleDir) - return sampleDir - @pytest.fixture(scope="function") def nwFuncTemp(nwTemp): funcDir = path.join(nwTemp, "ftemp") @@ -66,11 +74,24 @@ def nwFuncTemp(nwTemp): shutil.rmtree(funcDir) return -@pytest.fixture(scope="session") -def nwRef(): +@pytest.fixture(scope="function") +def nwMinimal(nwTemp): testDir = path.dirname(__file__) - refDir = path.join(testDir, "reference") - return refDir + minimalStore = path.join(testDir, "minimal") + minimalDir = path.join(nwTemp, "minimal") + if path.isdir(minimalDir): + shutil.rmtree(minimalDir) + shutil.copytree(minimalStore, minimalDir) + cacheDir = path.join(minimalDir, "cache") + if path.isdir(cacheDir): + shutil.rmtree(cacheDir) + metaDir = path.join(minimalDir, "meta") + if path.isdir(metaDir): + shutil.rmtree(metaDir) + yield minimalDir + if path.isdir(minimalDir): + shutil.rmtree(minimalDir) + return @pytest.fixture(scope="session") def nwLipsum(): diff --git a/tests/minimal/ToC.json b/tests/minimal/ToC.json new file mode 100644 index 00000000..5881c392 --- /dev/null +++ b/tests/minimal/ToC.json @@ -0,0 +1,17 @@ +[ + [ + "content/8c659a11cd429.nwd", + "NOVEL", + "New Scene" + ], + [ + "content/a35baf2e93843.nwd", + "NOVEL", + "Title Page" + ], + [ + "content/f5ab3e30151e1.nwd", + "NOVEL", + "New Chapter" + ] +] \ No newline at end of file diff --git a/tests/minimal/ToC.txt b/tests/minimal/ToC.txt new file mode 100644 index 00000000..f5b94b72 --- /dev/null +++ b/tests/minimal/ToC.txt @@ -0,0 +1,10 @@ + + Table of Contents +=================== + + File Name Class Document Label +-------------------------------------------------------------------------------- + content/8c659a11cd429.nwd NOVEL New Scene + content/a35baf2e93843.nwd NOVEL Title Page + content/f5ab3e30151e1.nwd NOVEL New Chapter + diff --git a/tests/minimal/content/8c659a11cd429.nwd b/tests/minimal/content/8c659a11cd429.nwd new file mode 100644 index 00000000..5ecf5c59 --- /dev/null +++ b/tests/minimal/content/8c659a11cd429.nwd @@ -0,0 +1,3 @@ +%%~ 8c659a11cd429:a6d311a93600a:a508bb932959c:NOVEL:SCENE:New Scene +### New Scene + diff --git a/tests/minimal/content/a35baf2e93843.nwd b/tests/minimal/content/a35baf2e93843.nwd new file mode 100644 index 00000000..a7745e3b --- /dev/null +++ b/tests/minimal/content/a35baf2e93843.nwd @@ -0,0 +1,4 @@ +%%~ a35baf2e93843:a508bb932959c:NOVEL:TITLE:Title Page +# Minimal + +By Jane Doe, John Doh diff --git a/tests/minimal/content/f5ab3e30151e1.nwd b/tests/minimal/content/f5ab3e30151e1.nwd new file mode 100644 index 00000000..ba1c9faa --- /dev/null +++ b/tests/minimal/content/f5ab3e30151e1.nwd @@ -0,0 +1,3 @@ +%%~ f5ab3e30151e1:a6d311a93600a:a508bb932959c:NOVEL:CHAPTER:New Chapter +## New Chapter + diff --git a/tests/minimal/meta/guiOptions.json b/tests/minimal/meta/guiOptions.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/minimal/meta/guiOptions.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/minimal/meta/sessionStats.log b/tests/minimal/meta/sessionStats.log new file mode 100644 index 00000000..38cbde3d --- /dev/null +++ b/tests/minimal/meta/sessionStats.log @@ -0,0 +1,2 @@ +# Start Time End Time Novel Notes +2020-08-28 11:36:36 2020-08-28 11:36:48 10 0 diff --git a/tests/minimal/meta/tagsIndex.json b/tests/minimal/meta/tagsIndex.json new file mode 100644 index 00000000..ec600a1c --- /dev/null +++ b/tests/minimal/meta/tagsIndex.json @@ -0,0 +1,91 @@ +{ + "tagIndex": {}, + "refIndex": { + "a35baf2e93843": { + "T000000": { + "tags": [], + "updated": 1598607396 + }, + "T000001": { + "tags": [], + "updated": 1598607396 + } + }, + "f5ab3e30151e1": { + "T000000": { + "tags": [], + "updated": 1598607396 + }, + "T000001": { + "tags": [], + "updated": 1598607396 + } + }, + "8c659a11cd429": { + "T000000": { + "tags": [], + "updated": 1598607396 + }, + "T000001": { + "tags": [], + "updated": 1598607396 + } + } + }, + "novelIndex": { + "a35baf2e93843": { + "T000001": { + "level": "H1", + "title": "Minimal", + "layout": "TITLE", + "synopsis": "", + "cCount": 7, + "wCount": 1, + "pCount": 0, + "updated": 1598607396 + } + }, + "f5ab3e30151e1": { + "T000001": { + "level": "H2", + "title": "New Chapter", + "layout": "CHAPTER", + "synopsis": "", + "cCount": 11, + "wCount": 2, + "pCount": 0, + "updated": 1598607396 + } + }, + "8c659a11cd429": { + "T000001": { + "level": "H3", + "title": "New Scene", + "layout": "SCENE", + "synopsis": "", + "cCount": 9, + "wCount": 2, + "pCount": 0, + "updated": 1598607396 + } + } + }, + "noteIndex": {}, + "textCounts": { + "a35baf2e93843": [ + 28, + 6, + 1 + ], + "f5ab3e30151e1": [ + 11, + 2, + 0 + ], + "8c659a11cd429": [ + 9, + 2, + 0 + ] + } +} \ No newline at end of file diff --git a/tests/minimal/nwProject.nwx b/tests/minimal/nwProject.nwx new file mode 100644 index 00000000..af99a8ce --- /dev/null +++ b/tests/minimal/nwProject.nwx @@ -0,0 +1,115 @@ + + + + Test Minimal + Minimal + Jane Doe + John Doh + 1 + 1 + 8 + + + True + False + True + None + None + 10 + 10 + 0 + + + %title% + Chapter %ch%: %title% + %title% + * * * +
+
+ + New + Note + Draft + Finished + + + New + Minor + Major + Main + +
+ + + Novel + ROOT + NOVEL + New + False + + + Title Page + FILE + NOVEL + New + True + TITLE + 28 + 6 + 1 + 0 + + + New Chapter + FOLDER + NOVEL + New + False + + + New Chapter + FILE + NOVEL + New + True + CHAPTER + 11 + 2 + 0 + 0 + + + New Scene + FILE + NOVEL + New + True + SCENE + 9 + 2 + 0 + 0 + + + Plot + ROOT + PLOT + New + False + + + Characters + ROOT + CHARACTER + New + False + + + World + ROOT + WORLD + New + False + + +
diff --git a/tests/reference/proj/3_nwProject.nwx b/tests/reference/proj/3_nwProject.nwx index 0c396343..c2be9007 100644 --- a/tests/reference/proj/3_nwProject.nwx +++ b/tests/reference/proj/3_nwProject.nwx @@ -1,9 +1,9 @@ - + New Project - 5 + 2 1 0 @@ -37,7 +37,7 @@ Main - + Novel ROOT @@ -109,35 +109,7 @@ 0 0 - - Timeline - ROOT - TIMELINE - New - False - - - Object - ROOT - OBJECT - New - False - - - Custom1 - ROOT - CUSTOM - New - False - - - Custom2 - ROOT - CUSTOM - New - False - - + Hello FILE NOVEL @@ -149,7 +121,7 @@ 0 0 - + Jane FILE CHARACTER diff --git a/tests/test_project.py b/tests/test_project.py index 005bac2b..4e90a8c4 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -4,63 +4,66 @@ import pytest from os import path +from shutil import copyfile from nwtools import cmpFiles -from nwdummy import DummyMain -from nw.config import Config from nw.core.project import NWProject from nw.core.index import NWIndex from nw.constants import nwItemClass -theConf = Config() -theMain = DummyMain() -theMain.mainConf = theConf - -theProject = NWProject(theMain) -theProject.projTree.setSeed(42) - @pytest.mark.project -def testProjectNewMinimal(nwTempProj, nwRef, nwTemp): - projFile = path.join(nwTempProj, "nwProject.nwx") +def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy): + projFile = path.join(nwFuncTemp, "nwProject.nwx") + testFile = path.join(nwTempProj, "1_nwProject.nwx") refFile = path.join(nwRef, "proj", "1_nwProject.nwx") - assert theConf.initConfig(nwRef, nwTemp) - assert theProject.newProject({"projPath": nwTempProj}) - assert theProject.setProjectPath(nwTempProj) + + theProject = NWProject(nwDummy) + theProject.projTree.setSeed(42) + + assert theProject.newProject({"projPath": nwFuncTemp}) + assert theProject.setProjectPath(nwFuncTemp) assert theProject.saveProject() assert theProject.closeProject() - assert cmpFiles(projFile, refFile, [2, 6, 7, 8]) -@pytest.mark.project -def testProjectOpen(nwTempProj): - projFile = path.join(nwTempProj, "nwProject.nwx") + # Check the new project + copyfile(projFile, testFile) + assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) + + # Open again assert theProject.openProject(projFile) -@pytest.mark.project -def testProjectSave(nwTempProj, nwRef): - projFile = path.join(nwTempProj, "nwProject.nwx") - refFile = path.join(nwRef, "proj", "1_nwProject.nwx") + # Save and close assert theProject.saveProject() assert theProject.closeProject() - assert cmpFiles(projFile, refFile, [2, 6, 7, 8]) + copyfile(projFile, testFile) + assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) assert not theProject.projChanged -@pytest.mark.project -def testProjectOpenTwice(nwTempProj, nwRef): - projFile = path.join(nwTempProj, "nwProject.nwx") - refFile = path.join(nwRef, "proj", "1_nwProject.nwx") + # Open a second time assert theProject.openProject(projFile) assert not theProject.openProject(projFile) assert theProject.openProject(projFile, overrideLock=True) assert theProject.saveProject() assert theProject.closeProject() - assert cmpFiles(projFile, refFile, [2, 6, 7, 8]) + copyfile(projFile, testFile) + assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) @pytest.mark.project -def testProjectNewRoot(nwTempProj, nwRef): - projFile = path.join(nwTempProj, "nwProject.nwx") +def testProjectNewRoot(nwFuncTemp, nwTempProj, nwRef, nwDummy): + projFile = path.join(nwFuncTemp, "nwProject.nwx") + testFile = path.join(nwTempProj, "2_nwProject.nwx") refFile = path.join(nwRef, "proj", "2_nwProject.nwx") + + theProject = NWProject(nwDummy) + theProject.projTree.setSeed(42) + + assert theProject.newProject({"projPath": nwFuncTemp}) + assert theProject.setProjectPath(nwFuncTemp) + assert theProject.saveProject() + assert theProject.closeProject() assert theProject.openProject(projFile) + assert isinstance(theProject.newRoot("Novel", nwItemClass.NOVEL), type(None)) assert isinstance(theProject.newRoot("Plot", nwItemClass.PLOT), type(None)) assert isinstance(theProject.newRoot("Character", nwItemClass.CHARACTER), type(None)) @@ -69,31 +72,48 @@ def testProjectNewRoot(nwTempProj, nwRef): assert isinstance(theProject.newRoot("Object", nwItemClass.OBJECT), str) assert isinstance(theProject.newRoot("Custom1", nwItemClass.CUSTOM), str) assert isinstance(theProject.newRoot("Custom2", nwItemClass.CUSTOM), str) + assert theProject.projChanged assert theProject.saveProject() assert theProject.closeProject() - assert cmpFiles(projFile, refFile, [2, 6, 7, 8]) + + copyfile(projFile, testFile) + assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) assert not theProject.projChanged @pytest.mark.project -def testProjectNewFile(nwTempProj, nwRef): - projFile = path.join(nwTempProj, "nwProject.nwx") +def testProjectNewFile(nwFuncTemp, nwTempProj, nwRef, nwDummy): + projFile = path.join(nwFuncTemp, "nwProject.nwx") + testFile = path.join(nwTempProj, "3_nwProject.nwx") refFile = path.join(nwRef, "proj", "3_nwProject.nwx") + + theProject = NWProject(nwDummy) + theProject.projTree.setSeed(42) + + assert theProject.newProject({"projPath": nwFuncTemp}) + assert theProject.setProjectPath(nwFuncTemp) + assert theProject.saveProject() + assert theProject.closeProject() assert theProject.openProject(projFile) - assert isinstance(theProject.newFile("Hello", nwItemClass.NOVEL, "73475cb40a568"), str) + + assert isinstance(theProject.newFile("Hello", nwItemClass.NOVEL, "31489056e0916"), str) assert isinstance(theProject.newFile("Jane", nwItemClass.CHARACTER, "71ee45a3c0db9"), str) assert theProject.projChanged assert theProject.saveProject() assert theProject.closeProject() - assert cmpFiles(projFile, refFile, [2, 6, 7, 8]) + + copyfile(projFile, testFile) + assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) assert not theProject.projChanged @pytest.mark.project -def testIndexScanThis(nwTempProj): - projFile = path.join(nwTempProj, "nwProject.nwx") - assert theProject.openProject(projFile) +def testIndexScanThis(nwMinimal, nwDummy): - theIndex = NWIndex(theProject, theMain) + theProject = NWProject(nwDummy) + theProject.projTree.setSeed(42) + assert theProject.openProject(nwMinimal) + + theIndex = NWIndex(theProject, nwDummy) isValid, theBits, thePos = theIndex.scanThis("tag: this, and this") assert not isValid @@ -135,15 +155,17 @@ def testIndexScanThis(nwTempProj): assert theProject.closeProject() @pytest.mark.project -def testIndexCheckThese(nwTempProj): - projFile = path.join(nwTempProj, "nwProject.nwx") - assert theProject.openProject(projFile) +def testIndexCheckThese(nwMinimal, nwDummy): - theIndex = NWIndex(theProject, theMain) - nHandle = "0e17daca5f3e1" - nItem = theProject.projTree[nHandle] - cHandle = "02d20bbd7e394" - cItem = theProject.projTree[cHandle] + theProject = NWProject(nwDummy) + theProject.projTree.setSeed(42) + assert theProject.openProject(nwMinimal) + + theIndex = NWIndex(theProject, nwDummy) + nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c") + cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER, "afb3043c7b2b3") + nItem = theProject.projTree[nHandle] + cItem = theProject.projTree[cHandle] assert theIndex.scanText(cHandle, ( "# Jane Smith\n" @@ -153,7 +175,7 @@ def testIndexCheckThese(nwTempProj): "# Hello World!\n" "@pov: Jane" )) - assert str(theIndex.tagIndex) == "{'Jane': [2, '02d20bbd7e394', 'CHARACTER', 'T000001']}" + assert str(theIndex.tagIndex) == "{'Jane': [2, '%s', 'CHARACTER', 'T000001']}" % cHandle assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!" assert str(theIndex.checkThese(["@tag", "Jane"], cItem)) == "[True, True]" @@ -168,13 +190,15 @@ def testIndexCheckThese(nwTempProj): assert theProject.closeProject() @pytest.mark.project -def testIndexMeta(nwTempProj): - projFile = path.join(nwTempProj, "nwProject.nwx") - assert theProject.openProject(projFile) +def testIndexMeta(nwMinimal, nwDummy): - theIndex = NWIndex(theProject, theMain) - nHandle = "0e17daca5f3e1" - cHandle = "02d20bbd7e394" + theProject = NWProject(nwDummy) + theProject.projTree.setSeed(42) + assert theProject.openProject(nwMinimal) + + theIndex = NWIndex(theProject, nwDummy) + nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c") + cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER, "afb3043c7b2b3") assert theIndex.scanText(cHandle, ( "# Jane Smith\n" @@ -191,11 +215,11 @@ def testIndexMeta(nwTempProj): "\n" "Well, not really.\n" )) - assert str(theIndex.tagIndex) == "{'Jane': [2, '02d20bbd7e394', 'CHARACTER', 'T000001']}" + assert str(theIndex.tagIndex) == "{'Jane': [2, '%s', 'CHARACTER', 'T000001']}" % cHandle assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!" # The novel structure should contain the pointer to the novel file header - assert str(theIndex.getNovelStructure()) == "['0e17daca5f3e1:T000001']" + assert str(theIndex.getNovelStructure()) == "['%s:T000001']" % nHandle # The novel file should have the correct counts cC, wC, pC = theIndex.getCounts(nHandle) @@ -210,21 +234,22 @@ def testIndexMeta(nwTempProj): # The character file should have a record of the reference from the novel file theRefs = theIndex.getBackReferenceList(cHandle) - assert str(theRefs) == "{'0e17daca5f3e1': 'T000001'}" + assert str(theRefs) == "{'%s': 'T000001'}" % nHandle assert theProject.closeProject() -# The two following tests must be at the end as they mess up the config object -# and the handle seed. They go into their own folders, but use the same project -# object as the test above. - @pytest.mark.project -def testProjectNewCustom(nwTempCustom, nwRef, nwTemp): +def testProjectNewCustom(nwFuncTemp, nwTempProj, nwRef, nwDummy): + + projFile = path.join(nwFuncTemp, "nwProject.nwx") + testFile = path.join(nwTempProj, "4_nwProject.nwx") + refFile = path.join(nwRef, "proj", "4_nwProject.nwx") + projData = { "projName": "Test Custom", "projTitle": "Test Novel", "projAuthors": "Jane Doe\nJohn Doh\n", - "projPath": nwTempCustom, + "projPath": nwFuncTemp, "popSample": False, "popMinimal": False, "popCustom": True, @@ -240,29 +265,33 @@ def testProjectNewCustom(nwTempCustom, nwRef, nwTemp): "numScenes": 3, "chFolders": True, } - theProject.mainConf = theConf + theProject = NWProject(nwDummy) theProject.projTree.setSeed(42) + assert theProject.newProject(projData) assert theProject.saveProject() assert theProject.closeProject() - projFile = path.join(nwTempCustom, "nwProject.nwx") - refFile = path.join(nwRef, "proj", "4_nwProject.nwx") - assert cmpFiles(projFile, refFile, [2, 6, 7, 8]) + + copyfile(projFile, testFile) + assert cmpFiles(testFile, refFile, [2, 6, 7, 8]) @pytest.mark.project -def testProjectNewSample(nwTempSample, nwLipsum, nwRef, nwTemp): +def testProjectNewSample(nwFuncTemp, nwRef, nwConf, nwDummy): projData = { "projName": "Test Sample", "projTitle": "Test Novel", "projAuthors": "Jane Doe\nJohn Doh\n", - "projPath": nwTempSample, + "projPath": nwFuncTemp, "popSample": True, "popMinimal": False, "popCustom": False, } - theProject.mainConf = theConf + theProject = NWProject(nwDummy) + theProject.projTree.setSeed(42) + theProject.mainConf = nwConf + assert theProject.newProject(projData) - assert theProject.openProject(nwTempSample) + assert theProject.openProject(nwFuncTemp) assert theProject.projName == "Sample Project" assert theProject.saveProject() assert theProject.closeProject()