def testCoreProject_AccessItems(nwMinimal, mockGUI): """Test helper functions for the project folder. """ theProject = NWProject(mockGUI) theProject.openProject(nwMinimal) # Move Novel ROOT to after its files oldOrder = [ "a508bb932959c", # ROOT: Novel "a35baf2e93843", # FILE: Title Page "a6d311a93600a", # FOLDER: New Chapter "f5ab3e30151e1", # FILE: New Chapter "8c659a11cd429", # FILE: New Scene "7695ce551d265", # ROOT: Plot "afb3043c7b2b3", # ROOT: Characters "9d5247ab588e0", # ROOT: World ] newOrder = [ "a35baf2e93843", # FILE: Title Page "f5ab3e30151e1", # FILE: New Chapter "8c659a11cd429", # FILE: New Scene "a6d311a93600a", # FOLDER: New Chapter "a508bb932959c", # ROOT: Novel "7695ce551d265", # ROOT: Plot "afb3043c7b2b3", # ROOT: Characters "9d5247ab588e0", # ROOT: World ] assert theProject.projTree.handles() == oldOrder assert theProject.setTreeOrder(newOrder) assert theProject.projTree.handles() == newOrder # Add a non-existing item theProject.projTree._treeOrder.append("01234567789abc") # Add an item with a non-existent parent nHandle = theProject.newFile("Test File", nwItemClass.NOVEL, "a6d311a93600a") theProject.projTree[nHandle].setParent("cba9876543210") assert theProject.projTree[nHandle].itemParent == "cba9876543210" retOrder = [] for tItem in theProject.getProjectItems(): retOrder.append(tItem.itemHandle) assert retOrder == [ "a508bb932959c", # ROOT: Novel "7695ce551d265", # ROOT: Plot "afb3043c7b2b3", # ROOT: Characters "9d5247ab588e0", # ROOT: World nHandle, # FILE: Test File "a35baf2e93843", # FILE: Title Page "a6d311a93600a", # FOLDER: New Chapter "f5ab3e30151e1", # FILE: New Chapter "8c659a11cd429", # FILE: New Scene ] assert theProject.projTree[nHandle].itemParent is None
def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir): """Test other project class methods and functions. """ theProject = NWProject(mockGUI) theProject.projTree.setSeed(42) assert theProject.openProject(nwMinimal) assert theProject.projPath == nwMinimal # Setting project path assert theProject.setProjectPath(None) assert theProject.projPath is None assert theProject.setProjectPath("") assert theProject.projPath is None assert theProject.setProjectPath("~") assert theProject.projPath == os.path.expanduser("~") # Create a new folder and populate it 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, "mock2") assert not theProject.setProjectPath(projPath, newProject=True) # Set back assert theProject.setProjectPath(nwMinimal) # Project Name assert theProject.setProjectName(" A Name ") assert theProject.projName == "A Name" # Project Title assert theProject.setBookTitle(" A Title ") assert theProject.bookTitle == "A Title" # Project Authors # Check that the list is cleaned up and that it can be extracted as # a properly formatted string, depending on number of names assert not theProject.setBookAuthors([]) assert theProject.setBookAuthors(" Jane Doe \n John Doh \n ") assert theProject.bookAuthors == ["Jane Doe", "John Doh"] assert theProject.setBookAuthors("") assert theProject.getAuthors() == "" assert theProject.setBookAuthors("Jane Doe") assert theProject.getAuthors() == "Jane Doe" assert theProject.setBookAuthors("Jane Doe\nJohn Doh") assert theProject.getAuthors() == "Jane Doe and John Doh" assert theProject.setBookAuthors("Jane Doe\nJohn Doh\nBod Owens") assert theProject.getAuthors() == "Jane Doe, John Doh and Bod Owens" # Edit Time theProject.editTime = 1234 theProject.projOpened = 1600000000 with monkeypatch.context() as mp: mp.setattr("novelwriter.core.project.time", lambda: 1600005600) assert theProject.getCurrentEditTime() == 6834 # Trash folder # Should create on first call, and just returned on later calls assert theProject.projTree["73475cb40a568"] is None assert theProject.trashFolder() == "73475cb40a568" assert theProject.trashFolder() == "73475cb40a568" # Project backup assert theProject.doBackup is True assert theProject.setProjBackup(False) assert theProject.doBackup is False assert not theProject.setProjBackup(True) theProject.mainConf.backupPath = tmpDir assert theProject.setProjBackup(True) assert theProject.setProjectName("") assert not theProject.setProjBackup(True) assert theProject.setProjectName("A Name") assert theProject.setProjBackup(True) # Spell check theProject.projChanged = False assert theProject.setSpellCheck(True) assert not theProject.setSpellCheck(False) assert theProject.projChanged # Spell language theProject.projChanged = False assert theProject.setSpellLang(None) assert theProject.projSpell is None assert theProject.setSpellLang("None") assert theProject.projSpell is None assert theProject.setSpellLang("en_GB") 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) assert not theProject.setAutoOutline(False) assert theProject.projChanged # Last edited theProject.projChanged = False assert theProject.setLastEdited("0123456789abc") assert theProject.lastEdited == "0123456789abc" assert theProject.projChanged # Last viewed theProject.projChanged = False assert theProject.setLastViewed("0123456789abc") assert theProject.lastViewed == "0123456789abc" assert theProject.projChanged # Autoreplace theProject.projChanged = False assert theProject.setAutoReplace({"A": "B", "C": "D"}) assert theProject.autoReplace == {"A": "B", "C": "D"} assert theProject.projChanged # Change project tree order oldOrder = [ "a508bb932959c", "a35baf2e93843", "a6d311a93600a", "f5ab3e30151e1", "8c659a11cd429", "7695ce551d265", "afb3043c7b2b3", "9d5247ab588e0", "73475cb40a568", ] newOrder = [ "f5ab3e30151e1", "8c659a11cd429", "7695ce551d265", "a508bb932959c", "a35baf2e93843", "a6d311a93600a", "afb3043c7b2b3", "9d5247ab588e0", ] assert theProject.projTree.handles() == oldOrder assert theProject.setTreeOrder(newOrder) assert theProject.projTree.handles() == newOrder assert theProject.setTreeOrder(oldOrder) assert theProject.projTree.handles() == oldOrder # Change status theProject.projTree["a35baf2e93843"].setStatus("Finished") theProject.projTree["a6d311a93600a"].setStatus("Draft") theProject.projTree["f5ab3e30151e1"].setStatus("Note") theProject.projTree["8c659a11cd429"].setStatus("Finished") newList = [ ("New", 1, 1, 1, "New"), ("Draft", 2, 2, 2, "Note"), # These are swapped ("Note", 3, 3, 3, "Draft"), # These are swapped ("Edited", 4, 4, 4, "Finished"), # Renamed ("Finished", 5, 5, 5, None), # New, with reused name ] assert theProject.setStatusColours(newList) assert theProject.statusItems._theLabels == [ "New", "Draft", "Note", "Edited", "Finished" ] assert theProject.statusItems._theColours == [(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5)] assert theProject.projTree[ "a35baf2e93843"].itemStatus == "Edited" # Renamed assert theProject.projTree["a6d311a93600a"].itemStatus == "Note" # Swapped assert theProject.projTree["f5ab3e30151e1"].itemStatus == "Draft" # Swapped assert theProject.projTree[ "8c659a11cd429"].itemStatus == "Edited" # Renamed # Change importance fHandle = theProject.newFile("Jane Doe", nwItemClass.CHARACTER, "afb3043c7b2b3") theProject.projTree[fHandle].setImport("Main") newList = [ ("New", 1, 1, 1, "New"), ("Minor", 2, 2, 2, "Minor"), ("Major", 3, 3, 3, "Major"), ("Min", 4, 4, 4, "Main"), ("Max", 5, 5, 5, None), ] assert theProject.setImportColours(newList) assert theProject.importItems._theLabels == [ "New", "Minor", "Major", "Min", "Max" ] assert theProject.importItems._theColours == [(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5)] assert theProject.projTree[fHandle].itemImport == "Min" # Check status counts assert theProject.statusItems._theCounts == [0, 0, 0, 0, 0] assert theProject.importItems._theCounts == [0, 0, 0, 0, 0] theProject.countStatus() assert theProject.statusItems._theCounts == [1, 1, 1, 2, 0] assert theProject.importItems._theCounts == [3, 0, 0, 1, 0] # Session stats theProject.currWCount = 200 theProject.lastWCount = 100 with monkeypatch.context() as mp: mp.setattr("os.path.isdir", lambda *a, **k: False) assert not theProject._appendSessionStats(idleTime=0) # Block open with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert not theProject._appendSessionStats(idleTime=0) # Write entry assert theProject.projMeta == os.path.join(nwMinimal, "meta") statsFile = os.path.join(theProject.projMeta, nwFiles.SESS_STATS) theProject.projOpened = 1600002000 theProject.currNovelWC = 200 theProject.currNotesWC = 100 with monkeypatch.context() as mp: mp.setattr("novelwriter.core.project.time", lambda: 1600005600) assert theProject._appendSessionStats(idleTime=99) assert readFile(statsFile) == ( "# Offset 100\n" "# Start Time End Time Novel Notes Idle\n" "%s %s 200 100 99\n") % ( formatTimeStamp(1600002000), formatTimeStamp(1600005600)) # Pack XML Value xElem = etree.Element("element") theProject._packProjectValue(xElem, "A", "B", allowNone=False) assert etree.tostring(xElem, pretty_print=False, encoding="utf-8") == (b"<element><A>B</A></element>") xElem = etree.Element("element") theProject._packProjectValue(xElem, "A", "", allowNone=False) assert etree.tostring(xElem, pretty_print=False, encoding="utf-8") == (b"<element/>") # Pack XML Key/Value xElem = etree.Element("element") theProject._packProjectKeyValue(xElem, "item", {"A": "B", "C": "D"}) assert etree.tostring(xElem, pretty_print=False, encoding="utf-8") == (b"<element>" b"<item>" b"<entry key=\"A\">B</entry>" b"<entry key=\"C\">D</entry>" b"</item>" b"</element>")