def testGuiAbout_Dialog(qtbot, monkeypatch, nwGUI): """Test the full about dialogs. """ # NW About monkeypatch.setattr(GuiAbout, "exec_", lambda *args: None) nwGUI.mainMenu.aAboutNW.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiAbout") is not None, timeout=1000) msgAbout = getGuiItem("GuiAbout") assert isinstance(msgAbout, GuiAbout) msgAbout.show() assert msgAbout.pageAbout.document().characterCount() > 100 assert msgAbout.pageNotes.document().characterCount() > 100 assert msgAbout.pageLicense.document().characterCount() > 100 msgAbout.mainConf.assetPath = "whatever" msgAbout._fillNotesPage() assert msgAbout.pageNotes.toPlainText( ) == "Error loading release notes text ..." msgAbout._fillLicensePage() assert msgAbout.pageLicense.toPlainText( ) == "Error loading license text ..." msgAbout.showReleaseNotes() assert msgAbout.tabBox.currentWidget() == msgAbout.pageNotes # Qt About monkeypatch.setattr(QMessageBox, "aboutQt", lambda *args, **kwargs: None) nwGUI.mainMenu.aAboutQt.activate(QAction.Trigger) # qtbot.stopForInteraction() msgAbout._doClose()
def testToolProjectWizard_Handling(qtbot, monkeypatch, nwGUI, nwMinimal): """Test the launch of the project wizard. Disabled for macOS because the test segfaults on QWizard.show() """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) ## # Test New Project Function ## # New with a project open should cause an error assert nwGUI.openProject(nwMinimal) with monkeypatch.context() as mp: mp.setattr(nwGUI, "closeProject", lambda *a: False) assert nwGUI.newProject() is False # Close project, but call with invalid path assert nwGUI.closeProject() with monkeypatch.context() as mp: mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: None) assert nwGUI.newProject() is False # Now, with an empty dictionary mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {}) assert nwGUI.newProject() is False # Now, with a non-empty folder mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {"projPath": nwMinimal}) assert nwGUI.newProject() is False ## # Test the Wizard Launching ## nwGUI.mainConf.lastPath = " " monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *a: None) result = nwGUI.showNewProjectDialog() qtbot.waitUntil(lambda: getGuiItem("GuiProjectWizard") is not None, timeout=1000) nwWiz = getGuiItem("GuiProjectWizard") assert isinstance(nwWiz, GuiProjectWizard) nwWiz.show() qtbot.wait(stepDelay) qtbot.mouseClick(nwWiz.button(QWizard.CancelButton), Qt.LeftButton) assert result is None with monkeypatch.context() as mp: mp.setattr(GuiProjectWizard, "result", lambda *a: QDialog.Accepted) result = nwGUI.showNewProjectDialog() nwWiz.button(QWizard.CancelButton).click() assert isinstance(result, dict) nwWiz.reject() nwWiz.close()
def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncProj): """Test launching the item editor dialog from GuiMain. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) # Block Dialog exec_ monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: None) # Open Editor wo/Project assert nwGUI.editItem() is False # Create and Open Project nwGUI.theProject.projTree.setSeed(42) assert nwGUI.newProject({"projPath": fncProj}) # No Selection nwGUI.treeView.clearSelection() assert nwGUI.editItem() is False # Force opening from editor assert nwGUI.openDocument("0e17daca5f3e1") nwGUI.isFocusMode = True # Block Tree Lookup with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) assert nwGUI.editItem() is False # Invalid Type nwGUI.theProject.projTree["0e17daca5f3e1"]._type = nwItemType.NO_TYPE assert nwGUI.editItem() is False nwGUI.theProject.projTree["0e17daca5f3e1"]._type = nwItemType.FILE # Open Properly assert nwGUI.editItem() is True qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000) itemEdit = getGuiItem("GuiItemEditor") assert itemEdit is not None itemEdit.close() # Open Via Menu with monkeypatch.context() as mp: mp.setattr(GuiItemEditor, "result", lambda *a: QDialog.Accepted) nwGUI.mainMenu.aEditItem.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000) itemEdit = getGuiItem("GuiItemEditor") assert itemEdit is not None itemEdit.close() nwGUI.isFocusMode = False
def testToolLipsum_Main(qtbot, monkeypatch, nwGUI, fncProj): """Test the Lorem Ipsum tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) # Check that we cannot open when there is no project nwGUI.mainMenu.aLipsumText.activate(QAction.Trigger) assert getGuiItem("GuiLipsum") is None # Create a new project nwGUI.theProject.projTree.setSeed(42) assert nwGUI.newProject({"projPath": fncProj}) is True assert nwGUI.openDocument("0e17daca5f3e1") is True assert len(nwGUI.docEditor.getText()) == 15 # Open the tool nwGUI.mainMenu.aLipsumText.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiLipsum") is not None, timeout=1000) nwLipsum = getGuiItem("GuiLipsum") assert isinstance(nwLipsum, GuiLipsum) # Insert paragraphs nwGUI.docEditor.setCursorPosition(100) # End of document nwLipsum.paraCount.setValue(2) nwLipsum._doInsert() theText = nwGUI.docEditor.getText() assert "Lorem ipsum" in theText assert len(theText) == 965 # Insert random paragraph nwGUI.docEditor.setCursorPosition(1000) # End of document nwLipsum.randSwitch.setChecked(True) nwLipsum.paraCount.setValue(1) nwLipsum._doInsert() theText = nwGUI.docEditor.getText() assert len(theText) > 965 # Close nwLipsum._doClose()
def testDlgAbout_NWDialog(qtbot, monkeypatch, nwGUI): """Test the novelWriter about dialogs. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) # NW About nwGUI.mainTheme.themeName = "A Theme" nwGUI.mainTheme.themeAuthor = "An Author" assert nwGUI.showAboutNWDialog(showNotes=True) is True qtbot.waitUntil(lambda: getGuiItem("GuiAbout") is not None, timeout=1000) msgAbout = getGuiItem("GuiAbout") assert isinstance(msgAbout, GuiAbout) assert msgAbout.pageAbout.document().characterCount() > 100 assert msgAbout.pageNotes.document().characterCount() > 100 assert msgAbout.pageLicense.document().characterCount() > 100 msgAbout.mainConf.assetPath = "whatever" msgAbout._fillNotesPage() assert msgAbout.pageNotes.toPlainText( ) == "Error loading release notes text ..." msgAbout._fillLicensePage() assert msgAbout.pageLicense.toPlainText( ) == "Error loading licence text ..." msgAbout.showReleaseNotes() assert msgAbout.tabBox.currentWidget() == msgAbout.pageNotes msgAbout._doClose() # Open Again from Menu nwGUI.mainMenu.aAboutNW.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiAbout") is not None, timeout=1000) msgAbout = getGuiItem("GuiAbout") assert msgAbout is not None msgAbout._doClose()
def testGuiLoadProject_Main(qtbot, monkeypatch, nwGUI, nwMinimal): """Test the load project wizard. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) assert nwGUI.openProject(nwMinimal) assert nwGUI.closeProject() qtbot.wait(stepDelay) monkeypatch.setattr(GuiProjectLoad, "exec_", lambda *args: None) monkeypatch.setattr(GuiProjectLoad, "result", lambda *args: QDialog.Accepted) nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000) nwLoad = getGuiItem("GuiProjectLoad") assert isinstance(nwLoad, GuiProjectLoad) nwLoad.show() qtbot.wait(stepDelay) recentCount = nwLoad.listBox.topLevelItemCount() assert recentCount > 0 qtbot.wait(stepDelay) selItem = nwLoad.listBox.topLevelItem(0) selPath = selItem.data(nwLoad.C_NAME, Qt.UserRole) assert isinstance(selItem, QTreeWidgetItem) qtbot.wait(stepDelay) nwLoad.selPath.setText("") nwLoad.listBox.setCurrentItem(selItem) nwLoad._doSelectRecent() assert nwLoad.selPath.text() == selPath qtbot.wait(stepDelay) qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Open), Qt.LeftButton) assert nwLoad.openPath == selPath assert nwLoad.openState == nwLoad.OPEN_STATE # Just create a new project load from scratch for the rest of the test del nwLoad qtbot.wait(stepDelay) nwGUI.mainMenu.aOpenProject.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiProjectLoad") is not None, timeout=1000) qtbot.wait(stepDelay) nwLoad = getGuiItem("GuiProjectLoad") assert isinstance(nwLoad, GuiProjectLoad) nwLoad.show() qtbot.wait(stepDelay) qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Cancel), Qt.LeftButton) assert nwLoad.openPath is None assert nwLoad.openState == nwLoad.NONE_STATE qtbot.wait(stepDelay) nwLoad.show() qtbot.mouseClick(nwLoad.newButton, Qt.LeftButton) assert nwLoad.openPath is None assert nwLoad.openState == nwLoad.NEW_STATE qtbot.wait(stepDelay) nwLoad.show() nwLoad._keyPressDelete() assert nwLoad.listBox.topLevelItemCount() == recentCount - 1 getFile = os.path.join(nwMinimal, "nwProject.nwx") monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *args, **kwargs: (getFile, None)) qtbot.mouseClick(nwLoad.browseButton, Qt.LeftButton) assert nwLoad.openPath == nwMinimal assert nwLoad.openState == nwLoad.OPEN_STATE nwLoad.close()
def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDir, refDir): """Test the full project settings dialog. """ projFile = os.path.join(fncProj, "nwProject.nwx") testFile = os.path.join(outDir, "guiProjSettings_Dialog_nwProject.nwx") compFile = os.path.join(refDir, "guiProjSettings_Dialog_nwProject.nwx") # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) # Check that we cannot open when there is no project nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger) assert getGuiItem("GuiProjectSettings") is None # Create new project nwGUI.theProject.projTree.setSeed(42) assert nwGUI.newProject({"projPath": fncProj}) nwGUI.mainConf.backupPath = fncDir nwGUI.theProject.setSpellLang("en") nwGUI.theProject.setBookAuthors("Jane Smith\nJohn Smith") nwGUI.theProject.setAutoReplace({"A": "B", "C": "D"}) # Get the dialog object monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *args: None) monkeypatch.setattr(GuiProjectSettings, "result", lambda *args: QDialog.Accepted) nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000) projEdit = getGuiItem("GuiProjectSettings") assert isinstance(projEdit, GuiProjectSettings) projEdit.show() qtbot.addWidget(projEdit) # Settings Tab # ============ assert projEdit.tabMain.editName.text() == "New Project" assert projEdit.tabMain.editTitle.text() == "" assert projEdit.tabMain.editAuthors.toPlainText( ) == "Jane Smith\nJohn Smith" assert projEdit.tabMain.spellLang.currentData() == "en" assert projEdit.tabMain.doBackup.isChecked() is False qtbot.wait(stepDelay) projEdit.tabMain.editName.setText("") for c in "Project Name": qtbot.keyClick(projEdit.tabMain.editName, c, delay=typeDelay) for c in "Project Title": qtbot.keyClick(projEdit.tabMain.editTitle, c, delay=typeDelay) projEdit.tabMain.editAuthors.clear() for c in "Jane Doe": qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=typeDelay) qtbot.keyClick(projEdit.tabMain.editAuthors, Qt.Key_Return, delay=keyDelay) for c in "John Doh": qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=typeDelay) qtbot.keyClick(projEdit.tabMain.editAuthors, Qt.Key_Return, delay=keyDelay) qtbot.wait(stepDelay) assert projEdit.tabMain.editName.text() == "Project Name" assert projEdit.tabMain.editTitle.text() == "Project Title" assert projEdit.tabMain.editAuthors.toPlainText() == "Jane Doe\nJohn Doh\n" # Status Tab # ========== projEdit._tabBox.setCurrentWidget(projEdit.tabStatus) assert projEdit.tabStatus.colChanged is False assert projEdit.tabStatus.getNewList() is None assert projEdit.tabStatus.listBox.topLevelItemCount() == 4 # Fake drag'n'drop should change changed status projEdit.tabStatus._rowsMoved() assert projEdit.tabStatus.colChanged is True projEdit.tabStatus.colChanged = False projEdit.tabStatus.listBox.clearSelection() assert projEdit.tabStatus._getSelectedItem() is None projEdit.tabStatus.listBox.topLevelItem(0).setSelected(True) assert isinstance(projEdit.tabStatus._getSelectedItem(), QTreeWidgetItem) # Can't delete the first item (it's in use) projEdit.tabStatus.listBox.clearSelection() projEdit.tabStatus.listBox.topLevelItem(0).setSelected(True) qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton) assert projEdit.tabStatus.listBox.topLevelItemCount() == 4 # Can delete the third item projEdit.tabStatus.listBox.clearSelection() projEdit.tabStatus.listBox.topLevelItem(2).setSelected(True) qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton) assert projEdit.tabStatus.listBox.topLevelItemCount() == 3 # Add a new item monkeypatch.setattr(QColorDialog, "getColor", lambda *args: QColor(20, 30, 40)) qtbot.mouseClick(projEdit.tabStatus.addButton, Qt.LeftButton) projEdit.tabStatus.listBox.topLevelItem(3).setSelected(True) for n in range(8): qtbot.keyClick(projEdit.tabStatus.editName, Qt.Key_Backspace, delay=typeDelay) for c in "Final": qtbot.keyClick(projEdit.tabStatus.editName, c, delay=typeDelay) qtbot.mouseClick(projEdit.tabStatus.colButton, Qt.LeftButton) qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton) assert projEdit.tabStatus.listBox.topLevelItemCount() == 4 qtbot.wait(stepDelay) assert projEdit.tabStatus.colChanged is True assert projEdit.tabStatus.getNewList() == [("New", 100, 100, 100, "New"), ("Note", 200, 50, 0, "Note"), ("Finished", 50, 200, 0, "Finished"), ("Final", 20, 30, 40, None)] # Importance Tab # ============== projEdit._tabBox.setCurrentWidget(projEdit.tabImport) projEdit.tabStatus.listBox.clearSelection() projEdit.tabImport.listBox.topLevelItem(3).setSelected(True) qtbot.mouseClick(projEdit.tabImport.delButton, Qt.LeftButton) qtbot.mouseClick(projEdit.tabImport.addButton, Qt.LeftButton) projEdit.tabStatus.listBox.clearSelection() projEdit.tabImport.listBox.topLevelItem(3).setSelected(True) for n in range(8): qtbot.keyClick(projEdit.tabImport.editName, Qt.Key_Backspace, delay=typeDelay) for c in "Final": qtbot.keyClick(projEdit.tabImport.editName, c, delay=typeDelay) qtbot.mouseClick(projEdit.tabImport.saveButton, Qt.LeftButton) qtbot.wait(stepDelay) # Auto-Replace Tab # ================ qtbot.wait(stepDelay) projEdit._tabBox.setCurrentWidget(projEdit.tabReplace) assert projEdit.tabReplace.listBox.topLevelItem(0).text(0) == "<A>" assert projEdit.tabReplace.listBox.topLevelItem(0).text(1) == "B" assert projEdit.tabReplace.listBox.topLevelItem(1).text(0) == "<C>" assert projEdit.tabReplace.listBox.topLevelItem(1).text(1) == "D" qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton) projEdit.tabReplace.listBox.topLevelItem(2).setSelected(True) projEdit.tabReplace.editKey.setText("") for c in "Th is ": qtbot.keyClick(projEdit.tabReplace.editKey, c, delay=typeDelay) projEdit.tabReplace.editValue.setText("") for c in "With This Stuff ": qtbot.keyClick(projEdit.tabReplace.editValue, c, delay=typeDelay) qtbot.mouseClick(projEdit.tabReplace.saveButton, Qt.LeftButton) qtbot.wait(stepDelay) projEdit.tabReplace.listBox.clearSelection() assert not projEdit.tabReplace._saveEntry() assert not projEdit.tabReplace._delEntry() qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton) newIdx = -1 for i in range(projEdit.tabReplace.listBox.topLevelItemCount()): if projEdit.tabReplace.listBox.topLevelItem(i).text(0) == "<keyword4>": newIdx = i break assert newIdx >= 0 newItem = projEdit.tabReplace.listBox.topLevelItem(newIdx) projEdit.tabReplace.listBox.setCurrentItem(newItem) qtbot.mouseClick(projEdit.tabReplace.delButton, Qt.LeftButton) qtbot.wait(stepDelay) # Save & Check # ============ projEdit._doSave() # Open again, and check project settings nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000) projEdit = getGuiItem("GuiProjectSettings") assert isinstance(projEdit, GuiProjectSettings) qtbot.addWidget(projEdit) assert projEdit.tabMain.editName.text() == "Project Name" assert projEdit.tabMain.editTitle.text() == "Project Title" theAuth = projEdit.tabMain.editAuthors.toPlainText().strip().splitlines() assert len(theAuth) == 2 assert theAuth[0] == "Jane Doe" assert theAuth[1] == "John Doh" projEdit._doClose() qtbot.wait(stepDelay) assert nwGUI.saveProject() qtbot.wait(stepDelay) # Check the files copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [2, 8, 9, 10])
def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir, outDir): """Test the full item editor dialog. """ projFile = os.path.join(fncProj, "nwProject.nwx") testFile = os.path.join(outDir, "guiItemEditor_Dialog_nwProject.nwx") compFile = os.path.join(refDir, "guiItemEditor_Dialog_nwProject.nwx") # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *args: True) # Create new, save, open project nwGUI.theProject.projTree.setSeed(42) assert nwGUI.newProject({"projPath": fncProj}) assert nwGUI.openDocument("0e17daca5f3e1") assert nwGUI.treeView.setSelectedHandle("0e17daca5f3e1", doScroll=True) monkeypatch.setattr(GuiItemEditor, "exec_", lambda *args: None) nwGUI.mainMenu.aEditItem.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000) itemEdit = getGuiItem("GuiItemEditor") assert isinstance(itemEdit, GuiItemEditor) itemEdit.show() qtbot.addWidget(itemEdit) assert itemEdit.editName.text() == "New Scene" assert itemEdit.editStatus.currentData() == "New" assert itemEdit.editLayout.currentData() == nwItemLayout.SCENE for c in "Just a Page": qtbot.keyClick(itemEdit.editName, c, delay=typeDelay) itemEdit.editStatus.setCurrentIndex(1) layoutIdx = itemEdit.editLayout.findData(nwItemLayout.PAGE) itemEdit.editLayout.setCurrentIndex(layoutIdx) itemEdit.editExport.setChecked(False) assert not itemEdit.editExport.isChecked() itemEdit._doSave() nwGUI.mainMenu.aEditItem.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiItemEditor") is not None, timeout=1000) itemEdit = getGuiItem("GuiItemEditor") assert isinstance(itemEdit, GuiItemEditor) itemEdit.show() qtbot.addWidget(itemEdit) assert itemEdit.editName.text() == "Just a Page" assert itemEdit.editStatus.currentData() == "Note" assert itemEdit.editLayout.currentData() == nwItemLayout.PAGE itemEdit._doClose() # Check that the header is updated nwGUI.docEditor.updateDocInfo("0e17daca5f3e1") assert nwGUI.docEditor.docHeader.theTitle.text( ) == "Novel › New Chapter › Just a Page" assert not nwGUI.docEditor.setCursorLine("where?") assert nwGUI.docEditor.setCursorLine(2) qtbot.wait(stepDelay) assert nwGUI.docEditor.getCursorPosition() == 15 qtbot.wait(stepDelay) assert nwGUI.saveProject() qtbot.wait(stepDelay) # Check the files copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [2, 6, 7, 8])
def testToolBuild_Main(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir): """Test the build tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda a, b, c, **kwargs: (c, None)) # Check that we cannot open when there is no project nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger) assert getGuiItem("GuiBuildNovel") is None # Open a project assert nwGUI.openProject(nwLipsum) # Open the tool nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiBuildNovel") is not None, timeout=1000) nwBuild = getGuiItem("GuiBuildNovel") assert isinstance(nwBuild, GuiBuildNovel) nwBuild.textFont.setText("DejaVu Sans") nwBuild.textSize.setValue(11) # Test Save # ========= # Invalid file format assert not nwBuild._saveDocument(-1) # Non-existent path with monkeypatch.context() as mp: mp.setattr("os.path.expanduser", lambda *args, **kwargs: nwLipsum) assert nwGUI.mainConf.lastPath != nwLipsum nwGUI.mainConf.lastPath = "no_such_path" assert nwBuild._saveDocument(nwBuild.FMT_NWD) assert nwGUI.mainConf.lastPath == nwLipsum # No path selected with monkeypatch.context() as mp: mp.setattr(QFileDialog, "getSaveFileName", lambda *args, **kwargs: ("", "")) assert not nwBuild._saveDocument(nwBuild.FMT_NWD) # Default Settings nwGUI.mainConf.lastPath = nwLipsum qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) assert nwBuild._saveDocument(nwBuild.FMT_NWD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_MD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.md") testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.md") compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.md") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_GH) projFile = os.path.join(nwLipsum, "Lorem Ipsum.md") testFile = os.path.join(outDir, "guiBuild_Tool_Step1G_Lorem_Ipsum.md") compFile = os.path.join(refDir, "guiBuild_Tool_Step1G_Lorem_Ipsum.md") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_FODT) projFile = os.path.join(nwLipsum, "Lorem Ipsum.fodt") testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.fodt") compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.fodt") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [4, 5]) # Change Title Formats and Flip Switches nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%") qtbot.wait(stepDelay) nwBuild.fmtScene.setText(r"Scene %ch%.%sc%: %title%") qtbot.wait(stepDelay) nwBuild.fmtSection.setText(r"%ch%.%sc%.1: %title%") qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.justifyText, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeSynopsis, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeKeywords, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.replaceUCode, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) assert nwBuild._saveDocument(nwBuild.FMT_NWD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_MD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.md") testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.md") compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.md") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_FODT) projFile = os.path.join(nwLipsum, "Lorem Ipsum.fodt") testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.fodt") compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.fodt") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [4, 5]) # Replace Tabs with Spaces qtbot.mouseClick(nwBuild.replaceTabs, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) # Save files that can be compared assert nwBuild._saveDocument(nwBuild.FMT_NWD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_MD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.md") testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.md") compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.md") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_FODT) projFile = os.path.join(nwLipsum, "Lorem Ipsum.fodt") testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.fodt") compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.fodt") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [4, 5]) # Putline Mode nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%") qtbot.wait(stepDelay) nwBuild.fmtScene.setText(r"Scene %sca%: %title%") qtbot.wait(stepDelay) nwBuild.fmtSection.setText(r"Section: %title%") qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeBody, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) # Save files that can be compared assert nwBuild._saveDocument(nwBuild.FMT_NWD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step4_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step4_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step4_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step4_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) # Check the JSON files too at this stage assert nwBuild._saveDocument(nwBuild.FMT_JSON_H) projFile = os.path.join(nwLipsum, "Lorem Ipsum.json") testFile = os.path.join(outDir, "guiBuild_Tool_Step4H_Lorem_Ipsum.json") compFile = os.path.join(refDir, "guiBuild_Tool_Step4H_Lorem_Ipsum.json") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [8]) assert nwBuild._saveDocument(nwBuild.FMT_JSON_M) projFile = os.path.join(nwLipsum, "Lorem Ipsum.json") testFile = os.path.join(outDir, "guiBuild_Tool_Step4M_Lorem_Ipsum.json") compFile = os.path.join(refDir, "guiBuild_Tool_Step4M_Lorem_Ipsum.json") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [8]) # Since odt and fodt is built by the same code, we don't check the # output. but just that the different format can be written as well assert nwBuild._saveDocument(nwBuild.FMT_ODT) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.odt")) # Print to PDF if not nwGUI.mainConf.osDarwin: assert nwBuild._saveDocument(nwBuild.FMT_PDF) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.pdf")) # Close the build tool htmlText = nwBuild.htmlText htmlStyle = nwBuild.htmlStyle buildTime = nwBuild.buildTime nwBuild._doClose() # Re-open build dialog from cahce nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiBuildNovel") is not None, timeout=1000) nwBuild = getGuiItem("GuiBuildNovel") assert isinstance(nwBuild, GuiBuildNovel) assert nwBuild.viewCachedDoc() assert nwBuild.htmlText == htmlText assert nwBuild.htmlStyle == htmlStyle assert nwBuild.buildTime == buildTime nwBuild._doClose()
def testGuiPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir): """Test the load project wizard. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) # Must create a clean config and GUI object as the test-wide # nw.CONFIG object is created on import an can be tainted by other tests confFile = os.path.join(fncDir, "novelwriter.conf") if os.path.isfile(confFile): os.unlink(confFile) theConf = Config() theConf.initConfig(fncDir, fncDir) theConf.setLastPath("") origConf = nw.CONFIG nw.CONFIG = theConf nwGUI = nw.main( ["--testmode", "--config=%s" % fncDir, "--data=%s" % fncDir]) qtbot.addWidget(nwGUI) nwGUI.show() qtbot.waitForWindowShown(nwGUI) qtbot.wait(20) theConf = nwGUI.mainConf assert theConf.confPath == fncDir monkeypatch.setattr(GuiPreferences, "exec_", lambda *args: None) monkeypatch.setattr(GuiPreferences, "result", lambda *args: QDialog.Accepted) nwGUI.mainMenu.aPreferences.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000) nwPrefs = getGuiItem("GuiPreferences") assert isinstance(nwPrefs, GuiPreferences) nwPrefs.show() assert nwPrefs.mainConf.confPath == fncDir # qtbot.stopForInteraction() # General Settings qtbot.wait(keyDelay) tabGeneral = nwPrefs.tabGeneral nwPrefs._tabBox.setCurrentWidget(tabGeneral) qtbot.wait(keyDelay) assert not tabGeneral.preferDarkIcons.isChecked() qtbot.mouseClick(tabGeneral.preferDarkIcons, Qt.LeftButton) assert tabGeneral.preferDarkIcons.isChecked() qtbot.wait(keyDelay) assert tabGeneral.showFullPath.isChecked() qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton) assert not tabGeneral.showFullPath.isChecked() qtbot.wait(keyDelay) assert not tabGeneral.hideVScroll.isChecked() qtbot.mouseClick(tabGeneral.hideVScroll, Qt.LeftButton) assert tabGeneral.hideVScroll.isChecked() qtbot.wait(keyDelay) assert not tabGeneral.hideHScroll.isChecked() qtbot.mouseClick(tabGeneral.hideHScroll, Qt.LeftButton) assert tabGeneral.hideHScroll.isChecked() # Check font button monkeypatch.setattr(QFontDialog, "getFont", lambda font, obj: (font, True)) qtbot.mouseClick(tabGeneral.fontButton, Qt.LeftButton) qtbot.wait(keyDelay) tabGeneral.guiFontSize.setValue(12) # Projects Settings qtbot.wait(keyDelay) tabProjects = nwPrefs.tabProjects nwPrefs._tabBox.setCurrentWidget(tabProjects) tabProjects.backupPath = "no/where" qtbot.wait(keyDelay) assert not tabProjects.backupOnClose.isChecked() qtbot.mouseClick(tabProjects.backupOnClose, Qt.LeftButton) assert tabProjects.backupOnClose.isChecked() # Check Browse button monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "") assert not tabProjects._backupFolder() monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args, **kwargs: "some/dir") qtbot.mouseClick(tabProjects.backupGetPath, Qt.LeftButton) qtbot.wait(keyDelay) tabProjects.autoSaveDoc.setValue(20) tabProjects.autoSaveProj.setValue(40) # Text Layout Settings qtbot.wait(keyDelay) tabLayout = nwPrefs.tabLayout nwPrefs._tabBox.setCurrentWidget(tabLayout) qtbot.wait(keyDelay) qtbot.mouseClick(tabLayout.fontButton, Qt.LeftButton) qtbot.wait(keyDelay) tabLayout.textStyleSize.setValue(13) tabLayout.textFlowMax.setValue(700) tabLayout.focusDocWidth.setValue(900) tabLayout.textMargin.setValue(45) tabLayout.tabWidth.setValue(45) qtbot.wait(keyDelay) assert not tabLayout.textFlowFixed.isChecked() qtbot.mouseClick(tabLayout.textFlowFixed, Qt.LeftButton) assert tabLayout.textFlowFixed.isChecked() qtbot.wait(keyDelay) assert not tabLayout.hideFocusFooter.isChecked() qtbot.mouseClick(tabLayout.hideFocusFooter, Qt.LeftButton) assert tabLayout.hideFocusFooter.isChecked() qtbot.wait(keyDelay) assert not tabLayout.textJustify.isChecked() qtbot.mouseClick(tabLayout.textJustify, Qt.LeftButton) assert tabLayout.textJustify.isChecked() qtbot.wait(keyDelay) assert tabLayout.scrollPastEnd.isChecked() qtbot.mouseClick(tabLayout.scrollPastEnd, Qt.LeftButton) assert not tabLayout.scrollPastEnd.isChecked() qtbot.wait(keyDelay) assert not tabLayout.autoScroll.isChecked() qtbot.mouseClick(tabLayout.autoScroll, Qt.LeftButton) assert tabLayout.autoScroll.isChecked() # Editor Settings qtbot.wait(keyDelay) tabEditing = nwPrefs.tabEditing nwPrefs._tabBox.setCurrentWidget(tabEditing) qtbot.wait(keyDelay) assert tabEditing.highlightQuotes.isChecked() qtbot.mouseClick(tabEditing.highlightQuotes, Qt.LeftButton) assert not tabEditing.highlightQuotes.isChecked() qtbot.wait(keyDelay) assert tabEditing.highlightEmph.isChecked() qtbot.mouseClick(tabEditing.highlightEmph, Qt.LeftButton) assert not tabEditing.highlightEmph.isChecked() qtbot.wait(keyDelay) assert not tabEditing.showTabsNSpaces.isChecked() qtbot.mouseClick(tabEditing.showTabsNSpaces, Qt.LeftButton) assert tabEditing.showTabsNSpaces.isChecked() qtbot.wait(keyDelay) assert not tabEditing.showLineEndings.isChecked() qtbot.mouseClick(tabEditing.showLineEndings, Qt.LeftButton) assert tabEditing.showLineEndings.isChecked() qtbot.wait(keyDelay) tabEditing.bigDocLimit.setValue(500) # Auto-Replace Settings qtbot.wait(keyDelay) tabAutoRep = nwPrefs.tabAutoRep nwPrefs._tabBox.setCurrentWidget(tabAutoRep) qtbot.wait(keyDelay) assert tabAutoRep.autoSelect.isChecked() qtbot.mouseClick(tabAutoRep.autoSelect, Qt.LeftButton) assert not tabAutoRep.autoSelect.isChecked() qtbot.wait(keyDelay) assert tabAutoRep.autoReplaceMain.isChecked() qtbot.mouseClick(tabAutoRep.autoReplaceMain, Qt.LeftButton) assert not tabAutoRep.autoReplaceMain.isChecked() qtbot.wait(keyDelay) assert not tabAutoRep.autoReplaceSQ.isEnabled() assert not tabAutoRep.autoReplaceDQ.isEnabled() assert not tabAutoRep.autoReplaceDash.isEnabled() assert not tabAutoRep.autoReplaceDots.isEnabled() monkeypatch.setattr(QuotesDialog, "selectedQuote", "'") monkeypatch.setattr(QuotesDialog, "exec_", lambda *args: QDialog.Accepted) qtbot.mouseClick(tabAutoRep.btnDoubleStyleC, Qt.LeftButton) # Save and Check Config qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton) nwPrefs._doClose() assert theConf.confChanged theConf.lastPath = "" assert nwGUI.mainConf.saveConfig() projFile = os.path.join(fncDir, "novelwriter.conf") testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf") compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf") copyfile(projFile, testFile) ignoreLines = [ 2, # Timestamp 9, # Release Notes 12, 13, 14, 15, 16, 17, 18, # Window sizes 7, 28, # Fonts (depends on system default) ] assert cmpFiles(testFile, compFile, ignoreLines) # Clean up nw.CONFIG = origConf nwGUI.closeMain()
def testGuiWritingStats_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj): """Test the full writing stats tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) # Create a project to work on assert nwGUI.newProject({"projPath": fncProj}) qtbot.wait(100) assert nwGUI.saveProject() sessFile = os.path.join(fncProj, "meta", nwFiles.SESS_STATS) # Open the Writing Stats dialog nwGUI.mainConf.lastPath = "" nwGUI.mainMenu.aWritingStats.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiWritingStats") is not None, timeout=1000) sessLog = getGuiItem("GuiWritingStats") assert isinstance(sessLog, GuiWritingStats) qtbot.wait(stepDelay) # Test Loading # ============ # No initial logfile assert not os.path.isfile(sessFile) assert not sessLog._loadLogFile() # Make a test log file writeFile( sessFile, ("# Offset 123\n" "# Start Time End Time Novel Notes\n" "2020-01-01 21:00:00 2020-01-01 21:00:05 6 0\n" "2020-01-03 21:00:00 2020-01-03 21:00:15 125 0\n" "2020-01-03 21:30:00 2020-01-03 21:30:15 125 5\n" "2020-01-06 21:00:00 2020-01-06 21:00:10 125 5\n")) assert os.path.isfile(sessFile) assert sessLog._loadLogFile() assert sessLog.wordOffset == 123 assert len(sessLog.logData) == 4 # Make sure a faulty file can still be read writeFile(sessFile, ("# Offset abc123\n" "# Start Time End Time Novel Notes\n" "2020-01-01 21:00:00 2020-01-01 21:00:05 6 0\n" "2020-01-03 21:00:00 2020-01-03 21:00:15 125 0\n" "2020-01-03 21:30:00 2020-01-03 21:30:15 125 5\n" "2020-01-06 21:00:00 2020-01-06 21:00:10 125\n")) assert sessLog._loadLogFile() assert sessLog.wordOffset == 0 assert len(sessLog.logData) == 3 # Test Exporting # ============== writeFile( sessFile, ("# Start Time End Time Novel Notes\n" "2020-01-01 21:00:00 2020-01-01 21:00:05 6 0\n" "2020-01-03 21:00:00 2020-01-03 21:00:15 125 0\n" "2020-01-03 21:30:00 2020-01-03 21:30:15 125 5\n" "2020-01-06 21:00:00 2020-01-06 21:00:10 125 5\n" "2020-01-08 21:00:00 2020-01-08 21:00:10 120 5\n")) sessLog.populateGUI() # Make the saving fail monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda *args, **kwargs: ("", "")) assert not sessLog._saveData(sessLog.FMT_CSV) assert not sessLog._saveData(sessLog.FMT_JSON) assert not sessLog._saveData(None) # Make the save succeed monkeypatch.setattr("os.path.expanduser", lambda *args: fncDir) monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda ss, tt, pp, options: (pp, "")) assert sessLog._saveData(sessLog.FMT_CSV) qtbot.wait(100) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(100) assert nwGUI.mainConf.lastPath == fncDir # Check the exported files jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert len(jsonData) == 4 assert jsonData[1]["length"] >= 14.0 assert jsonData[1]["newWords"] == 119 assert jsonData[1]["novelWords"] == 125 assert jsonData[1]["noteWords"] == 0 # Test Filters # ============ # No Novel Files qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) assert sessLog.novelWords.text() == "{:n}".format(120) assert sessLog.notesWords.text() == "{:n}".format(5) assert sessLog.totalWords.text() == "{:n}".format(125) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.loads(inFile.read()) assert len(jsonData) == 1 assert jsonData[0]["length"] >= 14.0 assert jsonData[0]["newWords"] == 5 assert jsonData[0]["novelWords"] == 125 assert jsonData[0]["noteWords"] == 5 # No Note Files qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton) qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert len(jsonData) == 3 assert jsonData[1]["length"] >= 14.0 assert jsonData[1]["newWords"] == 119 assert jsonData[1]["novelWords"] == 125 assert jsonData[1]["noteWords"] == 0 # No Negative Entries qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton) qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert len(jsonData) == 3 # Un-hide Zero Entries qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton) qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert len(jsonData) == 5 # Group by Day qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) # Check against both 1 and 2 as this can be 2 if test was started just before midnight. # A failed test should in any case produce a 4 assert len(jsonData) == 4 # IOError # ======= monkeypatch.setattr("builtins.open", causeOSError) assert not sessLog._loadLogFile() assert not sessLog._saveData(sessLog.FMT_CSV) # qtbot.stopForInteraction() sessLog._doClose() assert nwGUI.closeProject() qtbot.wait(stepDelay) monkeypatch.undo()
def testGuiMergeSplit_Tools(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir): """Test the full merge and split tools. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) nwGUI.theProject.projTree.setSeed(42) assert nwGUI.openProject(nwLipsum) qtbot.wait(stepDelay) assert nwGUI.treeView.setSelectedHandle("45e6b01ca35c1") qtbot.wait(stepDelay) monkeypatch.setattr(GuiDocMerge, "exec_", lambda *args: None) nwGUI.mainMenu.aMergeDocs.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocMerge") is not None, timeout=1000) nwMerge = getGuiItem("GuiDocMerge") assert isinstance(nwMerge, GuiDocMerge) nwMerge.show() qtbot.wait(stepDelay) nwMerge._doMerge() qtbot.wait(stepDelay) assert nwGUI.theProject.projTree["73475cb40a568"] is not None projFile = os.path.join(nwLipsum, "content", "73475cb40a568.nwd") testFile = os.path.join(outDir, "guiMerge_73475cb40a568.nwd") compFile = os.path.join(refDir, "guiMerge_73475cb40a568.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) # Split By Chapter assert nwGUI.treeView.setSelectedHandle("73475cb40a568") qtbot.wait(stepDelay) monkeypatch.setattr(GuiDocSplit, "exec_", lambda *args: None) nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000) nwSplit = getGuiItem("GuiDocSplit") assert isinstance(nwSplit, GuiDocSplit) nwSplit.show() qtbot.wait(stepDelay) nwSplit.splitLevel.setCurrentIndex(1) qtbot.wait(stepDelay) nwSplit._doSplit() assert nwGUI.theProject.projTree["71ee45a3c0db9"] is not None # This should give us back the file as it was before projFile = os.path.join(nwLipsum, "content", "71ee45a3c0db9.nwd") testFile = os.path.join(outDir, "guiMerge_71ee45a3c0db9.nwd") compFile = os.path.join(refDir, "guiMerge_73475cb40a568.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [1, 2, 3]) # Split By Scene assert nwGUI.treeView.setSelectedHandle("73475cb40a568") qtbot.wait(stepDelay) nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000) nwSplit = getGuiItem("GuiDocSplit") assert isinstance(nwSplit, GuiDocSplit) qtbot.wait(stepDelay) nwSplit.splitLevel.setCurrentIndex(2) qtbot.wait(stepDelay) nwSplit._doSplit() assert nwGUI.theProject.projTree["25fc0e7096fc6"] is not None assert nwGUI.theProject.projTree["31489056e0916"] is not None assert nwGUI.theProject.projTree["98010bd9270f9"] is not None projFile = os.path.join(nwLipsum, "content", "25fc0e7096fc6.nwd") testFile = os.path.join(outDir, "guiSplit_25fc0e7096fc6.nwd") compFile = os.path.join(refDir, "guiSplit_25fc0e7096fc6.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) projFile = os.path.join(nwLipsum, "content", "31489056e0916.nwd") testFile = os.path.join(outDir, "guiSplit_31489056e0916.nwd") compFile = os.path.join(refDir, "guiSplit_31489056e0916.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) projFile = os.path.join(nwLipsum, "content", "98010bd9270f9.nwd") testFile = os.path.join(outDir, "guiSplit_98010bd9270f9.nwd") compFile = os.path.join(refDir, "guiSplit_98010bd9270f9.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) # Split By Section assert nwGUI.treeView.setSelectedHandle("73475cb40a568") qtbot.wait(stepDelay) nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000) nwSplit = getGuiItem("GuiDocSplit") assert isinstance(nwSplit, GuiDocSplit) qtbot.wait(stepDelay) nwSplit.splitLevel.setCurrentIndex(3) qtbot.wait(stepDelay) nwSplit._doSplit() assert nwGUI.theProject.projTree["1a6562590ef19"] is not None assert nwGUI.theProject.projTree["031b4af5197ec"] is not None assert nwGUI.theProject.projTree["41cfc0d1f2d12"] is not None assert nwGUI.theProject.projTree["2858dcd1057d3"] is not None assert nwGUI.theProject.projTree["2fca346db6561"] is not None projFile = os.path.join(nwLipsum, "content", "1a6562590ef19.nwd") testFile = os.path.join(outDir, "guiSplit_1a6562590ef19.nwd") compFile = os.path.join(refDir, "guiSplit_25fc0e7096fc6.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [1, 2, 3]) projFile = os.path.join(nwLipsum, "content", "031b4af5197ec.nwd") testFile = os.path.join(outDir, "guiSplit_031b4af5197ec.nwd") compFile = os.path.join(refDir, "guiSplit_031b4af5197ec.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) projFile = os.path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd") testFile = os.path.join(outDir, "guiSplit_41cfc0d1f2d12.nwd") compFile = os.path.join(refDir, "guiSplit_41cfc0d1f2d12.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) projFile = os.path.join(nwLipsum, "content", "2858dcd1057d3.nwd") testFile = os.path.join(outDir, "guiSplit_2858dcd1057d3.nwd") compFile = os.path.join(refDir, "guiSplit_2858dcd1057d3.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) projFile = os.path.join(nwLipsum, "content", "2fca346db6561.nwd") testFile = os.path.join(outDir, "guiSplit_2fca346db6561.nwd") compFile = os.path.join(refDir, "guiSplit_2fca346db6561.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile)
def testGuiProjDetails_Dialog(qtbot, monkeypatch, nwGUI, nwLipsum): """Test the project details dialog. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "warning", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *args: QMessageBox.Yes) # Create a project to work on assert nwGUI.openProject(nwLipsum) assert nwGUI.rebuildIndex(beQuiet=True) qtbot.wait(100) # Open the Writing Stats dialog nwGUI.mainConf.lastPath = "" nwGUI.mainMenu.aProjectDetails.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiProjectDetails") is not None, timeout=1000) projDet = getGuiItem("GuiProjectDetails") assert isinstance(projDet, GuiProjectDetails) qtbot.wait(stepDelay) # Overview Page # ============= assert projDet.tabMain.bookTitle.text() == "Lorem Ipsum" assert projDet.tabMain.projName.text()[-11:] == "Lorem Ipsum" assert projDet.tabMain.bookAuthors.text()[-10:] == "lipsum.com" assert projDet.tabMain.wordCountVal.text() == f"{3000:n}" assert projDet.tabMain.chapCountVal.text() == f"{3:n}" assert projDet.tabMain.sceneCountVal.text() == f"{5:n}" assert projDet.tabMain.revCountVal.text( ) == f"{nwGUI.theProject.saveCount:n}" assert projDet.tabMain.projPathVal.text() == nwLipsum # Contents Page # ============= tocTab = projDet.tabContents tocTree = tocTab.tocTree assert tocTree.topLevelItemCount() == 7 assert tocTree.topLevelItem(0).text(tocTab.C_TITLE) == "Lorem Ipsum" assert tocTree.topLevelItem(2).text(tocTab.C_TITLE) == "Prologue" assert tocTree.topLevelItem(3).text(tocTab.C_TITLE) == "Act One" assert tocTree.topLevelItem(4).text(tocTab.C_TITLE) == "Chapter One" assert tocTree.topLevelItem(5).text(tocTab.C_TITLE) == "Chapter Two" assert tocTree.topLevelItem(6).text(tocTab.C_TITLE) == "END" # Count Pages tocTab.wpValue.setValue(100) tocTab.poValue.setValue(4) tocTab.dblValue.setChecked(False) tocTab._populateTree() thePages = ["1", "2", "1", "1", "11", "17", "0"] thePage = ["i", "ii", "1", "2", "3", "14", "31"] for i in range(7): assert tocTree.topLevelItem(i).text(tocTab.C_PAGES) == thePages[i] assert tocTree.topLevelItem(i).text(tocTab.C_PAGE) == thePage[i] tocTab.poValue.setValue(5) tocTab.dblValue.setChecked(True) tocTab._populateTree() thePages = ["2", "2", "2", "2", "12", "18", "0"] thePage = ["i", "iii", "1", "3", "5", "17", "35"] for i in range(7): assert tocTree.topLevelItem(i).text(tocTab.C_PAGES) == thePages[i] assert tocTree.topLevelItem(i).text(tocTab.C_PAGE) == thePage[i] # qtbot.stopForInteraction() # Clean Up projDet._doClose() nwGUI.closeMain() monkeypatch.undo()
def testGuiBuild_Tool(qtbot, monkeypatch, nwGUI, nwLipsum, refDir, outDir): """Test the build tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *args: QMessageBox.Yes) monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda a, b, c, **kwargs: (c, None)) # Check that we cannot open when there is no project nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger) assert getGuiItem("GuiBuildNovel") is None # Open a project assert nwGUI.openProject(nwLipsum) nwGUI.mainConf.lastPath = nwLipsum # Open the tool nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiBuildNovel") is not None, timeout=1000) nwBuild = getGuiItem("GuiBuildNovel") assert isinstance(nwBuild, GuiBuildNovel) # Default Settings qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) assert nwBuild._saveDocument(nwBuild.FMT_NWD) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step1_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step1_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) # Change Title Formats and Flip Switches nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%") qtbot.wait(stepDelay) nwBuild.fmtScene.setText(r"Scene %ch%.%sc%: %title%") qtbot.wait(stepDelay) nwBuild.fmtSection.setText(r"%ch%.%sc%.1: %title%") qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.justifyText, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeSynopsis, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeKeywords, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) assert nwBuild._saveDocument(nwBuild.FMT_NWD) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step2_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step2_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) # Replace Tabs with Spaces qtbot.mouseClick(nwBuild.replaceTabs, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) # Save files that can be compared assert nwBuild._saveDocument(nwBuild.FMT_NWD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step3_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step3_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) # Putline Mode nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%") qtbot.wait(stepDelay) nwBuild.fmtScene.setText(r"Scene %sca%: %title%") qtbot.wait(stepDelay) nwBuild.fmtSection.setText(r"Section: %title%") qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeComments, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.noteFiles, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.ignoreFlag, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.includeBody, Qt.LeftButton) qtbot.wait(stepDelay) qtbot.mouseClick(nwBuild.buildNovel, Qt.LeftButton) # Save files that can be compared assert nwBuild._saveDocument(nwBuild.FMT_NWD) projFile = os.path.join(nwLipsum, "Lorem Ipsum.nwd") testFile = os.path.join(outDir, "guiBuild_Tool_Step4_Lorem_Ipsum.nwd") compFile = os.path.join(refDir, "guiBuild_Tool_Step4_Lorem_Ipsum.nwd") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) assert nwBuild._saveDocument(nwBuild.FMT_HTM) projFile = os.path.join(nwLipsum, "Lorem Ipsum.htm") testFile = os.path.join(outDir, "guiBuild_Tool_Step4_Lorem_Ipsum.htm") compFile = os.path.join(refDir, "guiBuild_Tool_Step4_Lorem_Ipsum.htm") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile) # Check the JSON files too at this stage assert nwBuild._saveDocument(nwBuild.FMT_JSON_H) projFile = os.path.join(nwLipsum, "Lorem Ipsum.json") testFile = os.path.join(outDir, "guiBuild_Tool_Step4H_Lorem_Ipsum.json") compFile = os.path.join(refDir, "guiBuild_Tool_Step4H_Lorem_Ipsum.json") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [8]) assert nwBuild._saveDocument(nwBuild.FMT_JSON_M) projFile = os.path.join(nwLipsum, "Lorem Ipsum.json") testFile = os.path.join(outDir, "guiBuild_Tool_Step4M_Lorem_Ipsum.json") compFile = os.path.join(refDir, "guiBuild_Tool_Step4M_Lorem_Ipsum.json") copyfile(projFile, testFile) assert cmpFiles(testFile, compFile, [8]) # Save other file types handled by Qt # We assume the export itself by the Qt library works, so we just # check that novelWriter successfully writes the files. assert nwBuild._saveDocument(nwBuild.FMT_ODT) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.odt")) if not nwGUI.mainConf.osDarwin: assert nwBuild._saveDocument(nwBuild.FMT_PDF) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.pdf")) assert nwBuild._saveDocument(nwBuild.FMT_MD) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.md")) assert nwBuild._saveDocument(nwBuild.FMT_TXT) assert os.path.isfile(os.path.join(nwLipsum, "Lorem Ipsum.txt")) # Close the build tool htmlText = nwBuild.htmlText htmlStyle = nwBuild.htmlStyle nwdText = nwBuild.nwdText buildTime = nwBuild.buildTime nwBuild._doClose() # Re-open build dialog from cahce nwGUI.mainMenu.aBuildProject.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiBuildNovel") is not None, timeout=1000) nwBuild = getGuiItem("GuiBuildNovel") assert isinstance(nwBuild, GuiBuildNovel) assert nwBuild.viewCachedDoc() assert nwBuild.htmlText == htmlText assert nwBuild.htmlStyle == htmlStyle assert nwBuild.nwdText == nwdText assert nwBuild.buildTime == buildTime nwBuild._doClose()
def testToolProjectWizard_Main(qtbot, monkeypatch, nwGUI, nwMinimal): """Test the new project wizard. Disabled for macOS because the test segfaults on QWizard.show() """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) ## # Test New Project Function ## # New with a project open should cause an error assert nwGUI.openProject(nwMinimal) assert not nwGUI.newProject() # Close project, but call with invalid path assert nwGUI.closeProject() with monkeypatch.context() as mp: mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: None) assert not nwGUI.newProject() # Now, with an empty dictionary mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {}) assert not nwGUI.newProject() # Now, with a non-empty folder mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {"projPath": nwMinimal}) assert not nwGUI.newProject() ## # Test the Wizard ## monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *a: None) nwGUI.mainConf.lastPath = " " nwGUI.closeProject() nwGUI.showNewProjectDialog() qtbot.waitUntil(lambda: getGuiItem("GuiProjectWizard") is not None, timeout=1000) nwWiz = getGuiItem("GuiProjectWizard") assert isinstance(nwWiz, GuiProjectWizard) nwWiz.show() qtbot.wait(stepDelay) for wStep in range(4): # This does not actually create the project, it just generates the # dictionary that defines it. # Intro Page introPage = nwWiz.currentPage() assert isinstance(introPage, ProjWizardIntroPage) assert not nwWiz.button(QWizard.NextButton).isEnabled() qtbot.wait(stepDelay) for c in ("Test Minimal %d" % wStep): qtbot.keyClick(introPage.projName, c, delay=typeDelay) qtbot.wait(stepDelay) for c in "Minimal Novel": qtbot.keyClick(introPage.projTitle, c, delay=typeDelay) qtbot.wait(stepDelay) for c in "Jane Doe": qtbot.keyClick(introPage.projAuthors, c, delay=typeDelay) # Setting projName should activate the button assert nwWiz.button(QWizard.NextButton).isEnabled() qtbot.wait(stepDelay) qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton) # Folder Page storagePage = nwWiz.currentPage() assert isinstance(storagePage, ProjWizardFolderPage) assert not nwWiz.button(QWizard.NextButton).isEnabled() if wStep == 0: # Check invalid path first, the first time we reach here monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **kw: "") qtbot.wait(stepDelay) qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100) assert storagePage.projPath.text() == "" # Then, we always return nwMinimal as path monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **kw: nwMinimal) qtbot.wait(stepDelay) qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100) projPath = os.path.join(nwMinimal, "Test Minimal %d" % wStep) assert storagePage.projPath.text() == projPath # Setting projPath should activate the button assert nwWiz.button(QWizard.NextButton).isEnabled() qtbot.wait(stepDelay) qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton) # Populate Page popPage = nwWiz.currentPage() assert isinstance(popPage, ProjWizardPopulatePage) assert nwWiz.button(QWizard.NextButton).isEnabled() qtbot.wait(stepDelay) if wStep == 0: popPage.popMinimal.setChecked(True) elif wStep == 1: popPage.popCustom.setChecked(True) elif wStep == 2: popPage.popCustom.setChecked(True) elif wStep == 3: popPage.popSample.setChecked(True) qtbot.wait(stepDelay) qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton) # Custom Page if wStep == 1 or wStep == 2: customPage = nwWiz.currentPage() assert isinstance(customPage, ProjWizardCustomPage) assert nwWiz.button(QWizard.NextButton).isEnabled() customPage.addPlot.setChecked(True) customPage.addChar.setChecked(True) customPage.addWorld.setChecked(True) customPage.addTime.setChecked(True) customPage.addObject.setChecked(True) customPage.addEntity.setChecked(True) if wStep == 2: customPage.numChapters.setValue(0) customPage.numScenes.setValue(10) customPage.chFolders.setChecked(False) qtbot.wait(stepDelay) qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton) # Final Page finalPage = nwWiz.currentPage() assert isinstance(finalPage, ProjWizardFinalPage) assert nwWiz.button( QWizard.FinishButton).isEnabled() # But we don't click it # Check Data projData = nwGUI._assembleProjectWizardData(nwWiz) assert projData["projName"] == "Test Minimal %d" % wStep assert projData["projTitle"] == "Minimal Novel" assert projData["projAuthors"] == "Jane Doe" assert projData["projPath"] == projPath assert projData["popMinimal"] == (wStep == 0) assert projData["popCustom"] == (wStep == 1 or wStep == 2) assert projData["popSample"] == (wStep == 3) if wStep == 1 or wStep == 2: assert projData["addRoots"] == [ nwItemClass.PLOT, nwItemClass.CHARACTER, nwItemClass.WORLD, nwItemClass.TIMELINE, nwItemClass.OBJECT, nwItemClass.ENTITY, ] if wStep == 1: assert projData["numChapters"] == 5 assert projData["numScenes"] == 5 assert projData["chFolders"] else: assert projData["numChapters"] == 0 assert projData["numScenes"] == 10 assert not projData["chFolders"] else: assert projData["addRoots"] == [] assert projData["numChapters"] == 0 assert projData["numScenes"] == 0 assert not projData["chFolders"] # Restart the wizard for next iteration nwWiz.restart() nwWiz.reject() nwWiz.close()
def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): """Test the merge documents tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True)) # Create a new project buildTestProject(nwGUI, fncProj) # Handles for new objects hNovelRoot = "0000000000008" hChapterDir = "000000000000d" hChapterOne = "000000000000e" hSceneOne = "000000000000f" hSceneTwo = "0000000000010" hSceneThree = "0000000000011" hSceneFour = "0000000000012" hMergedDoc = "0000000000023" # Add Project Content nwGUI.switchFocus(nwWidget.TREE) nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hChapterDir).setSelected(True) nwGUI.projView.projTree.newTreeItem(nwItemType.FILE) nwGUI.projView.projTree.newTreeItem(nwItemType.FILE) nwGUI.projView.projTree.newTreeItem(nwItemType.FILE) assert nwGUI.saveProject() is True assert nwGUI.closeProject() is True tChapterOne = "## Chapter One\n\n% Chapter one comment\n" tSceneOne = "### Scene One\n\nThere once was a man from Nantucket" tSceneTwo = "### Scene Two\n\nWho kept all his cash in a bucket." tSceneThree = "### Scene Three\n\n\tBut his daughter, named Nan, \n\tRan away with a man" tSceneFour = "### Scene Four\n\nAnd as for the bucket, Nantucket." contentDir = os.path.join(fncProj, "content") writeFile(os.path.join(contentDir, hChapterOne+".nwd"), tChapterOne) writeFile(os.path.join(contentDir, hSceneOne+".nwd"), tSceneOne) writeFile(os.path.join(contentDir, hSceneTwo+".nwd"), tSceneTwo) writeFile(os.path.join(contentDir, hSceneThree+".nwd"), tSceneThree) writeFile(os.path.join(contentDir, hSceneFour+".nwd"), tSceneFour) assert nwGUI.openProject(fncProj) is True # Open the Merge tool nwGUI.switchFocus(nwWidget.TREE) nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hChapterDir).setSelected(True) monkeypatch.setattr(GuiDocMerge, "exec_", lambda *a: None) nwGUI.mainMenu.aMergeDocs.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocMerge") is not None, timeout=1000) nwMerge = getGuiItem("GuiDocMerge") assert isinstance(nwMerge, GuiDocMerge) nwMerge.show() qtbot.wait(50) # Populate List # ============= nwMerge.listBox.clear() assert nwMerge.listBox.count() == 0 # No item selected nwGUI.projView.projTree.clearSelection() assert nwMerge._populateList() is False assert nwMerge.listBox.count() == 0 # Non-existing item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hChapterDir).setSelected(True) assert nwMerge._populateList() is False assert nwMerge.listBox.count() == 0 # Select a non-folder nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hChapterOne).setSelected(True) assert nwMerge._populateList() is False assert nwMerge.listBox.count() == 0 # Select the chapter folder nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hChapterDir).setSelected(True) assert nwMerge._populateList() is True assert nwMerge.listBox.count() == 5 # Merge Documents # =============== # First, a successful merge with monkeypatch.context() as mp: mp.setattr(GuiDocMerge, "_doClose", lambda *a: None) assert nwMerge._doMerge() is True assert nwGUI.saveProject() is True mergedFile = os.path.join(contentDir, hMergedDoc+".nwd") assert os.path.isfile(mergedFile) assert readFile(mergedFile) == ( "%%%%~name: New Chapter\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" "%s\n\n" "%s\n\n" "%s\n\n" "%s\n\n" ) % ( hNovelRoot, hMergedDoc, tChapterOne.strip(), tSceneOne.strip(), tSceneTwo.strip(), tSceneThree.strip(), tSceneFour.strip(), ) # OS error with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert nwMerge._doMerge() is False # Can't find the source item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) assert nwMerge._doMerge() is False # No source handle set nwMerge.sourceItem = None assert nwMerge._doMerge() is False # No documents to merge nwMerge.listBox.clear() assert nwMerge._doMerge() is False # Close up nwMerge._doClose()
def testDlgWordList_Dialog(qtbot, monkeypatch, nwGUI, nwMinimal): """test the word list editor. """ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) monkeypatch.setattr(GuiWordList, "exec_", lambda *a: None) monkeypatch.setattr(GuiWordList, "result", lambda *a: QDialog.Accepted) monkeypatch.setattr(GuiWordList, "accept", lambda *a: None) # Open project nwGUI.openProject(nwMinimal) qtbot.wait(stepDelay) dictFile = os.path.join(nwMinimal, "meta", nwFiles.PROJ_DICT) # Load the dialog nwGUI.mainMenu.aEditWordList.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiWordList") is not None, timeout=1000) wList = getGuiItem("GuiWordList") assert isinstance(wList, GuiWordList) wList.show() qtbot.wait(stepDelay) # List should be blank assert wList.listBox.count() == 0 # Add words writeFile( dictFile, ( "word_a\n" "word_c\n" "word_g\n" " \n" # Should be ignored "word_f\n" "word_b\n")) qtbot.wait(stepDelay) assert wList._loadWordList() # Check that the content was loaded assert wList.listBox.item(0).text() == "word_a" assert wList.listBox.item(1).text() == "word_b" assert wList.listBox.item(2).text() == "word_c" assert wList.listBox.item(3).text() == "word_f" assert wList.listBox.item(4).text() == "word_g" # Add a blank word wList.newEntry.setText(" ") assert not wList._doAdd() # Add an existing word wList.newEntry.setText("word_c") assert not wList._doAdd() # Add a new word wList.newEntry.setText("word_d") assert wList._doAdd() # Check that the content now assert wList.listBox.item(0).text() == "word_a" assert wList.listBox.item(1).text() == "word_b" assert wList.listBox.item(2).text() == "word_c" assert wList.listBox.item(3).text() == "word_d" assert wList.listBox.item(4).text() == "word_f" assert wList.listBox.item(5).text() == "word_g" # Delete a word wList.newEntry.setText("delete_me") assert wList._doAdd() assert wList.listBox.item(0).text() == "delete_me" delItem = wList.listBox.findItems("delete_me", Qt.MatchExactly)[0] assert delItem.text() == "delete_me" delItem.setSelected(True) wList._doDelete() assert wList.listBox.findItems("delete_me", Qt.MatchExactly) == [] assert wList.listBox.item(0).text() == "word_a" # Save files assert wList._doSave() assert readFile(dictFile) == ("word_a\n" "word_b\n" "word_c\n" "word_d\n" "word_f\n" "word_g\n") # Save again and make it fail monkeypatch.setattr("builtins.open", causeOSError) assert not wList._doSave() # qtbot.stopForInteraction() wList._doClose()
def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir): """Test the load project wizard. """ # Block message box monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes) # Must create a clean config and GUI object as the test-wide # novelwriter.CONFIG object is created on import an can be tainted by other tests confFile = os.path.join(fncDir, "novelwriter.conf") if os.path.isfile(confFile): os.unlink(confFile) theConf = Config() theConf.initConfig(fncDir, fncDir) theConf.setLastPath("") origConf = novelwriter.CONFIG novelwriter.CONFIG = theConf nwGUI = novelwriter.main( ["--testmode", "--config=%s" % fncDir, "--data=%s" % fncDir]) qtbot.addWidget(nwGUI) nwGUI.show() qtbot.wait(stepDelay) theConf = nwGUI.mainConf assert theConf.confPath == fncDir monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None) monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted) monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")]) nwGUI.mainMenu.aPreferences.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000) nwPrefs = getGuiItem("GuiPreferences") assert isinstance(nwPrefs, GuiPreferences) nwPrefs.show() assert nwPrefs.mainConf.confPath == fncDir # General Settings qtbot.wait(keyDelay) tabGeneral = nwPrefs.tabGeneral nwPrefs._tabBox.setCurrentWidget(tabGeneral) qtbot.wait(keyDelay) assert tabGeneral.showFullPath.isChecked() qtbot.mouseClick(tabGeneral.showFullPath, Qt.LeftButton) assert not tabGeneral.showFullPath.isChecked() qtbot.wait(keyDelay) assert not tabGeneral.hideVScroll.isChecked() qtbot.mouseClick(tabGeneral.hideVScroll, Qt.LeftButton) assert tabGeneral.hideVScroll.isChecked() qtbot.wait(keyDelay) assert not tabGeneral.hideHScroll.isChecked() qtbot.mouseClick(tabGeneral.hideHScroll, Qt.LeftButton) assert tabGeneral.hideHScroll.isChecked() # Check font button monkeypatch.setattr(QFontDialog, "getFont", lambda font, obj: (font, True)) qtbot.mouseClick(tabGeneral.fontButton, Qt.LeftButton) qtbot.wait(keyDelay) tabGeneral.guiFontSize.setValue(12) # Projects Settings qtbot.wait(keyDelay) tabProjects = nwPrefs.tabProjects nwPrefs._tabBox.setCurrentWidget(tabProjects) tabProjects.backupPath = "no/where" qtbot.wait(keyDelay) assert not tabProjects.backupOnClose.isChecked() qtbot.mouseClick(tabProjects.backupOnClose, Qt.LeftButton) assert tabProjects.backupOnClose.isChecked() # qtbot.stopForInteraction() # Check Browse button monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "") assert not tabProjects._backupFolder() monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "some/dir") qtbot.mouseClick(tabProjects.backupGetPath, Qt.LeftButton) qtbot.wait(keyDelay) tabProjects.autoSaveDoc.setValue(20) tabProjects.autoSaveProj.setValue(40) # Document Settings qtbot.wait(keyDelay) tabDocs = nwPrefs.tabDocs nwPrefs._tabBox.setCurrentWidget(tabDocs) qtbot.wait(keyDelay) qtbot.mouseClick(tabDocs.fontButton, Qt.LeftButton) qtbot.wait(keyDelay) tabDocs.textSize.setValue(13) tabDocs.textWidth.setValue(700) tabDocs.focusWidth.setValue(900) tabDocs.textMargin.setValue(45) tabDocs.tabWidth.setValue(45) qtbot.wait(keyDelay) assert not tabDocs.hideFocusFooter.isChecked() qtbot.mouseClick(tabDocs.hideFocusFooter, Qt.LeftButton) assert tabDocs.hideFocusFooter.isChecked() qtbot.wait(keyDelay) assert not tabDocs.doJustify.isChecked() qtbot.mouseClick(tabDocs.doJustify, Qt.LeftButton) assert tabDocs.doJustify.isChecked() # Editor Settings qtbot.wait(keyDelay) tabEditor = nwPrefs.tabEditor nwPrefs._tabBox.setCurrentWidget(tabEditor) qtbot.wait(keyDelay) assert not tabEditor.showTabsNSpaces.isChecked() qtbot.mouseClick(tabEditor.showTabsNSpaces, Qt.LeftButton) assert tabEditor.showTabsNSpaces.isChecked() qtbot.wait(keyDelay) assert not tabEditor.showLineEndings.isChecked() qtbot.mouseClick(tabEditor.showLineEndings, Qt.LeftButton) assert tabEditor.showLineEndings.isChecked() qtbot.wait(keyDelay) assert not tabEditor.autoScroll.isChecked() qtbot.mouseClick(tabEditor.autoScroll, Qt.LeftButton) assert tabEditor.autoScroll.isChecked() qtbot.wait(keyDelay) tabEditor.scrollPastEnd.setValue(0) qtbot.wait(keyDelay) tabEditor.bigDocLimit.setValue(500) # Syntax Settings qtbot.wait(keyDelay) tabSyntax = nwPrefs.tabSyntax nwPrefs._tabBox.setCurrentWidget(tabSyntax) qtbot.wait(keyDelay) assert tabSyntax.highlightQuotes.isChecked() qtbot.mouseClick(tabSyntax.highlightQuotes, Qt.LeftButton) assert not tabSyntax.highlightQuotes.isChecked() qtbot.wait(keyDelay) assert tabSyntax.highlightEmph.isChecked() qtbot.mouseClick(tabSyntax.highlightEmph, Qt.LeftButton) assert not tabSyntax.highlightEmph.isChecked() # Automation Settings qtbot.wait(keyDelay) tabAuto = nwPrefs.tabAuto nwPrefs._tabBox.setCurrentWidget(tabAuto) qtbot.wait(keyDelay) assert tabAuto.autoSelect.isChecked() qtbot.mouseClick(tabAuto.autoSelect, Qt.LeftButton) assert not tabAuto.autoSelect.isChecked() qtbot.wait(keyDelay) assert tabAuto.doReplace.isChecked() qtbot.mouseClick(tabAuto.doReplace, Qt.LeftButton) assert not tabAuto.doReplace.isChecked() qtbot.wait(keyDelay) assert not tabAuto.doReplaceSQuote.isEnabled() assert not tabAuto.doReplaceDQuote.isEnabled() assert not tabAuto.doReplaceDash.isEnabled() assert not tabAuto.doReplaceDots.isEnabled() # Quotation Style qtbot.wait(keyDelay) tabQuote = nwPrefs.tabQuote nwPrefs._tabBox.setCurrentWidget(tabQuote) monkeypatch.setattr(GuiQuoteSelect, "selectedQuote", "'") monkeypatch.setattr(GuiQuoteSelect, "exec_", lambda *args: QDialog.Accepted) qtbot.mouseClick(tabQuote.btnDoubleStyleC, Qt.LeftButton) # Save and Check Config qtbot.mouseClick(nwPrefs.buttonBox.button(QDialogButtonBox.Ok), Qt.LeftButton) nwPrefs._doClose() assert theConf.confChanged theConf.lastPath = "" assert nwGUI.mainConf.saveConfig() projFile = os.path.join(fncDir, "novelwriter.conf") testFile = os.path.join(outDir, "guiPreferences_novelwriter.conf") compFile = os.path.join(refDir, "guiPreferences_novelwriter.conf") copyfile(projFile, testFile) ignTuple = ("timestamp", "guifont", "lastnotes", "guilang", "geometry", "preferences", "treecols", "novelcols", "projcols", "mainpane", "docpane", "viewpane", "outlinepane", "textfont", "textsize") assert cmpFiles(testFile, compFile, ignoreStart=ignTuple) # Clean up novelwriter.CONFIG = origConf nwGUI.closeMain()
def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj): """Test the merge documents tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) # Create a new project nwGUI.theProject.projTree.setSeed(42) assert nwGUI.newProject({"projPath": fncProj}) # Handles for new objects hChapterDir = "31489056e0916" hChapterOne = "98010bd9270f9" hSceneOne = "0e17daca5f3e1" hSceneTwo = "1a6562590ef19" hSceneThree = "031b4af5197ec" hSceneFour = "41cfc0d1f2d12" hMergedDoc = "2858dcd1057d3" # Add Project Content monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: QDialog.Accepted) nwGUI.switchFocus(nwWidget.TREE) nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True) nwGUI.treeView.newTreeItem(nwItemType.FILE, None) nwGUI.treeView.newTreeItem(nwItemType.FILE, None) nwGUI.treeView.newTreeItem(nwItemType.FILE, None) assert nwGUI.saveProject() is True assert nwGUI.closeProject() is True tChapterOne = "## Chapter One\n\n% Chapter one comment\n" tSceneOne = "### Scene One\n\nThere once was a man from Nantucket" tSceneTwo = "### Scene Two\n\nWho kept all his cash in a bucket." tSceneThree = "### Scene Three\n\n\tBut his daughter, named Nan, \n\tRan away with a man" tSceneFour = "### Scene Four\n\nAnd as for the bucket, Nantucket." contentDir = os.path.join(fncProj, "content") writeFile(os.path.join(contentDir, hChapterOne+".nwd"), tChapterOne) writeFile(os.path.join(contentDir, hSceneOne+".nwd"), tSceneOne) writeFile(os.path.join(contentDir, hSceneTwo+".nwd"), tSceneTwo) writeFile(os.path.join(contentDir, hSceneThree+".nwd"), tSceneThree) writeFile(os.path.join(contentDir, hSceneFour+".nwd"), tSceneFour) assert nwGUI.openProject(fncProj) is True # Open the Merge tool nwGUI.switchFocus(nwWidget.TREE) nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True) monkeypatch.setattr(GuiDocMerge, "exec_", lambda *a: None) nwGUI.mainMenu.aMergeDocs.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocMerge") is not None, timeout=1000) nwMerge = getGuiItem("GuiDocMerge") assert isinstance(nwMerge, GuiDocMerge) nwMerge.show() qtbot.wait(50) # Populate List # ============= nwMerge.listBox.clear() assert nwMerge.listBox.count() == 0 # No item selected nwGUI.treeView.clearSelection() assert nwMerge._populateList() is False assert nwMerge.listBox.count() == 0 # Non-existing item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True) assert nwMerge._populateList() is False assert nwMerge.listBox.count() == 0 # Select a non-folder nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hChapterOne).setSelected(True) assert nwMerge._populateList() is False assert nwMerge.listBox.count() == 0 # Select the chapter folder nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True) assert nwMerge._populateList() is True assert nwMerge.listBox.count() == 5 # Merge Documents # =============== # First, a successful merge with monkeypatch.context() as mp: mp.setattr(GuiDocMerge, "_doClose", lambda *a: None) assert nwMerge._doMerge() is True assert nwGUI.saveProject() is True mergedFile = os.path.join(contentDir, hMergedDoc+".nwd") assert os.path.isfile(mergedFile) assert readFile(mergedFile) == ( "%%%%~name: New Chapter\n" "%%%%~path: 73475cb40a568/2858dcd1057d3\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" "%s\n\n" "%s\n\n" "%s\n\n" "%s\n\n" ) % ( tChapterOne.strip(), tSceneOne.strip(), tSceneTwo.strip(), tSceneThree.strip(), tSceneFour.strip(), ) # OS error with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert nwMerge._doMerge() is False # Can't find the source item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) assert nwMerge._doMerge() is False # No source handle set nwMerge.sourceItem = None assert nwMerge._doMerge() is False # No documents to merge nwMerge.listBox.clear() assert nwMerge._doMerge() is False # Close up nwMerge._doClose()
def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj): """Test the full writing stats tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "warning", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) # Create a project to work on assert nwGUI.newProject({"projPath": fncProj}) qtbot.wait(100) assert nwGUI.saveProject() sessFile = os.path.join(fncProj, "meta", nwFiles.SESS_STATS) # Open the Writing Stats dialog nwGUI.mainConf.lastPath = "" nwGUI.mainMenu.aWritingStats.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiWritingStats") is not None, timeout=1000) sessLog = getGuiItem("GuiWritingStats") assert isinstance(sessLog, GuiWritingStats) qtbot.wait(stepDelay) # Test Loading # ============ # No initial logfile assert not os.path.isfile(sessFile) assert not sessLog._loadLogFile() # Make a test log file writeFile(sessFile, ( "# Offset 123\n" "# Start Time End Time Novel Notes Idle\n" "2020-01-01 21:00:00 2020-01-01 21:00:05 6 0\n" "2020-01-03 21:00:00 2020-01-03 21:00:15 125 0\n" "2020-01-03 21:30:00 2020-01-03 21:30:15 125 5\n" "2020-01-06 21:00:00 2020-01-06 21:00:10 125 5\n")) assert os.path.isfile(sessFile) assert sessLog._loadLogFile() assert sessLog.wordOffset == 123 assert len(sessLog.logData) == 4 # Make sure a faulty file can still be read writeFile(sessFile, ( "# Offset abc123\n" "# Start Time End Time Novel Notes Idle\n" "2020-01-01 21:00:00 2020-01-01 21:00:05 6 0 50\n" "2020-01-03 21:00:00 2020-01-03 21:00:15 125 0\n" "2020-01-03 21:30:00 2020-01-03 21:30:15 125 5\n" "2020-01-06 21:00:00 2020-01-06 21:00:10 125\n")) assert sessLog._loadLogFile() assert sessLog.wordOffset == 0 assert len(sessLog.logData) == 3 # Test Exporting # ============== writeFile(sessFile, ( "# Offset 1075\n" "# Start Time End Time Novel Notes Idle\n" "2021-01-31 19:00:00 2021-01-31 19:30:00 700 375 0\n" "2021-02-01 19:00:00 2021-02-01 19:30:00 700 375 10\n" "2021-02-01 20:00:00 2021-02-01 20:30:00 600 275 20\n" "2021-02-02 19:00:00 2021-02-02 19:30:00 750 425 30\n" "2021-02-02 20:00:00 2021-02-02 20:30:00 690 365 40\n" "2021-02-03 19:00:00 2021-02-03 19:30:00 680 355 50\n" "2021-02-04 19:00:00 2021-02-04 19:30:00 700 375 60\n" "2021-02-05 19:00:00 2021-02-05 19:30:00 500 175 70\n" "2021-02-06 19:00:00 2021-02-06 19:30:00 600 275 80\n" "2021-02-07 19:00:00 2021-02-07 19:30:00 600 275 90\n" )) sessLog.populateGUI() # Make the saving fail monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda *a, **k: ("", "")) assert not sessLog._saveData(sessLog.FMT_CSV) assert not sessLog._saveData(sessLog.FMT_JSON) assert not sessLog._saveData(None) # Make the save succeed monkeypatch.setattr("os.path.expanduser", lambda *a: fncDir) monkeypatch.setattr(QFileDialog, "getSaveFileName", lambda ss, tt, pp, options: (pp, "")) sessLog.listBox.sortByColumn(sessLog.C_TIME, 0) assert sessLog.novelWords.text() == "{:n}".format(600) assert sessLog.notesWords.text() == "{:n}".format(275) assert sessLog.totalWords.text() == "{:n}".format(875) assert sessLog.listBox.topLevelItem(0).text( sessLog.C_COUNT) == "{:n}".format(1) assert sessLog.listBox.topLevelItem(1).text( sessLog.C_COUNT) == "{:n}".format(-200) assert sessLog.listBox.topLevelItem(2).text( sessLog.C_COUNT) == "{:n}".format(300) assert sessLog.listBox.topLevelItem(3).text( sessLog.C_COUNT) == "{:n}".format(-120) assert sessLog.listBox.topLevelItem(4).text( sessLog.C_COUNT) == "{:n}".format(-20) assert sessLog.listBox.topLevelItem(5).text( sessLog.C_COUNT) == "{:n}".format(40) assert sessLog.listBox.topLevelItem(6).text( sessLog.C_COUNT) == "{:n}".format(-400) assert sessLog.listBox.topLevelItem(7).text( sessLog.C_COUNT) == "{:n}".format(200) assert sessLog._saveData(sessLog.FMT_CSV) qtbot.wait(100) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(100) assert nwGUI.mainConf.lastPath == fncDir # Check the exported files jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert jsonData == [{ "date": "2021-01-31 19:00:00", "length": 1800.0, "newWords": 1, "novelWords": 700, "noteWords": 375, "idleTime": 0 }, { "date": "2021-02-01 20:00:00", "length": 1800.0, "newWords": -200, "novelWords": 600, "noteWords": 275, "idleTime": 20 }, { "date": "2021-02-02 19:00:00", "length": 1800.0, "newWords": 300, "novelWords": 750, "noteWords": 425, "idleTime": 30 }, { "date": "2021-02-02 20:00:00", "length": 1800.0, "newWords": -120, "novelWords": 690, "noteWords": 365, "idleTime": 40 }, { "date": "2021-02-03 19:00:00", "length": 1800.0, "newWords": -20, "novelWords": 680, "noteWords": 355, "idleTime": 50 }, { "date": "2021-02-04 19:00:00", "length": 1800.0, "newWords": 40, "novelWords": 700, "noteWords": 375, "idleTime": 60 }, { "date": "2021-02-05 19:00:00", "length": 1800.0, "newWords": -400, "novelWords": 500, "noteWords": 175, "idleTime": 70 }, { "date": "2021-02-06 19:00:00", "length": 1800.0, "newWords": 200, "novelWords": 600, "noteWords": 275, "idleTime": 80 }] # Test Filters # ============ # No Novel Files qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.loads(inFile.read()) assert sessLog.listBox.topLevelItem(0).text( sessLog.C_COUNT) == "{:n}".format(1) assert sessLog.listBox.topLevelItem(1).text( sessLog.C_COUNT) == "{:n}".format(-100) assert sessLog.listBox.topLevelItem(2).text( sessLog.C_COUNT) == "{:n}".format(150) assert sessLog.listBox.topLevelItem(3).text( sessLog.C_COUNT) == "{:n}".format(-60) assert sessLog.listBox.topLevelItem(4).text( sessLog.C_COUNT) == "{:n}".format(-10) assert sessLog.listBox.topLevelItem(5).text( sessLog.C_COUNT) == "{:n}".format(20) assert sessLog.listBox.topLevelItem(6).text( sessLog.C_COUNT) == "{:n}".format(-200) assert sessLog.listBox.topLevelItem(7).text( sessLog.C_COUNT) == "{:n}".format(100) assert jsonData == [{ "date": "2021-01-31 19:00:00", "length": 1800.0, "newWords": 1, "novelWords": 700, "noteWords": 375, "idleTime": 0 }, { "date": "2021-02-01 20:00:00", "length": 1800.0, "newWords": -100, "novelWords": 600, "noteWords": 275, "idleTime": 20 }, { "date": "2021-02-02 19:00:00", "length": 1800.0, "newWords": 150, "novelWords": 750, "noteWords": 425, "idleTime": 30 }, { "date": "2021-02-02 20:00:00", "length": 1800.0, "newWords": -60, "novelWords": 690, "noteWords": 365, "idleTime": 40 }, { "date": "2021-02-03 19:00:00", "length": 1800.0, "newWords": -10, "novelWords": 680, "noteWords": 355, "idleTime": 50 }, { "date": "2021-02-04 19:00:00", "length": 1800.0, "newWords": 20, "novelWords": 700, "noteWords": 375, "idleTime": 60 }, { "date": "2021-02-05 19:00:00", "length": 1800.0, "newWords": -200, "novelWords": 500, "noteWords": 175, "idleTime": 70 }, { "date": "2021-02-06 19:00:00", "length": 1800.0, "newWords": 100, "novelWords": 600, "noteWords": 275, "idleTime": 80 }] # No Note Files qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton) qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert sessLog.listBox.topLevelItem(0).text( sessLog.C_COUNT) == "{:n}".format(1) assert sessLog.listBox.topLevelItem(1).text( sessLog.C_COUNT) == "{:n}".format(-100) assert sessLog.listBox.topLevelItem(2).text( sessLog.C_COUNT) == "{:n}".format(150) assert sessLog.listBox.topLevelItem(3).text( sessLog.C_COUNT) == "{:n}".format(-60) assert sessLog.listBox.topLevelItem(4).text( sessLog.C_COUNT) == "{:n}".format(-10) assert sessLog.listBox.topLevelItem(5).text( sessLog.C_COUNT) == "{:n}".format(20) assert sessLog.listBox.topLevelItem(6).text( sessLog.C_COUNT) == "{:n}".format(-200) assert sessLog.listBox.topLevelItem(7).text( sessLog.C_COUNT) == "{:n}".format(100) assert jsonData == [{ "date": "2021-01-31 19:00:00", "length": 1800.0, "newWords": 1, "novelWords": 700, "noteWords": 375, "idleTime": 0 }, { "date": "2021-02-01 20:00:00", "length": 1800.0, "newWords": -100, "novelWords": 600, "noteWords": 275, "idleTime": 20 }, { "date": "2021-02-02 19:00:00", "length": 1800.0, "newWords": 150, "novelWords": 750, "noteWords": 425, "idleTime": 30 }, { "date": "2021-02-02 20:00:00", "length": 1800.0, "newWords": -60, "novelWords": 690, "noteWords": 365, "idleTime": 40 }, { "date": "2021-02-03 19:00:00", "length": 1800.0, "newWords": -10, "novelWords": 680, "noteWords": 355, "idleTime": 50 }, { "date": "2021-02-04 19:00:00", "length": 1800.0, "newWords": 20, "novelWords": 700, "noteWords": 375, "idleTime": 60 }, { "date": "2021-02-05 19:00:00", "length": 1800.0, "newWords": -200, "novelWords": 500, "noteWords": 175, "idleTime": 70 }, { "date": "2021-02-06 19:00:00", "length": 1800.0, "newWords": 100, "novelWords": 600, "noteWords": 275, "idleTime": 80 }] # No Negative Entries qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton) qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) # qtbot.stopForInteraction() jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert sessLog.listBox.topLevelItem(0).text( sessLog.C_COUNT) == "{:n}".format(1) assert sessLog.listBox.topLevelItem(1).text( sessLog.C_COUNT) == "{:n}".format(300) assert sessLog.listBox.topLevelItem(2).text( sessLog.C_COUNT) == "{:n}".format(40) assert sessLog.listBox.topLevelItem(3).text( sessLog.C_COUNT) == "{:n}".format(200) assert jsonData == [{ "date": "2021-01-31 19:00:00", "length": 1800.0, "newWords": 1, "novelWords": 700, "noteWords": 375, "idleTime": 0 }, { "date": "2021-02-02 19:00:00", "length": 1800.0, "newWords": 300, "novelWords": 750, "noteWords": 425, "idleTime": 30 }, { "date": "2021-02-04 19:00:00", "length": 1800.0, "newWords": 40, "novelWords": 700, "noteWords": 375, "idleTime": 60 }, { "date": "2021-02-06 19:00:00", "length": 1800.0, "newWords": 200, "novelWords": 600, "noteWords": 275, "idleTime": 80 }] # Un-hide Zero Entries qtbot.mouseClick(sessLog.hideNegative, Qt.LeftButton) qtbot.mouseClick(sessLog.hideZeros, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert sessLog.listBox.topLevelItem(0).text( sessLog.C_COUNT) == "{:n}".format(1) assert sessLog.listBox.topLevelItem(1).text( sessLog.C_COUNT) == "{:n}".format(0) assert sessLog.listBox.topLevelItem(2).text( sessLog.C_COUNT) == "{:n}".format(-200) assert sessLog.listBox.topLevelItem(3).text( sessLog.C_COUNT) == "{:n}".format(300) assert sessLog.listBox.topLevelItem(4).text( sessLog.C_COUNT) == "{:n}".format(-120) assert sessLog.listBox.topLevelItem(5).text( sessLog.C_COUNT) == "{:n}".format(-20) assert sessLog.listBox.topLevelItem(6).text( sessLog.C_COUNT) == "{:n}".format(40) assert sessLog.listBox.topLevelItem(7).text( sessLog.C_COUNT) == "{:n}".format(-400) assert sessLog.listBox.topLevelItem(8).text( sessLog.C_COUNT) == "{:n}".format(200) assert sessLog.listBox.topLevelItem(9).text( sessLog.C_COUNT) == "{:n}".format(0) assert jsonData == [{ "date": "2021-01-31 19:00:00", "length": 1800.0, "newWords": 1, "novelWords": 700, "noteWords": 375, "idleTime": 0 }, { "date": "2021-02-01 19:00:00", "length": 1800.0, "newWords": 0, "novelWords": 700, "noteWords": 375, "idleTime": 10 }, { "date": "2021-02-01 20:00:00", "length": 1800.0, "newWords": -200, "novelWords": 600, "noteWords": 275, "idleTime": 20 }, { "date": "2021-02-02 19:00:00", "length": 1800.0, "newWords": 300, "novelWords": 750, "noteWords": 425, "idleTime": 30 }, { "date": "2021-02-02 20:00:00", "length": 1800.0, "newWords": -120, "novelWords": 690, "noteWords": 365, "idleTime": 40 }, { "date": "2021-02-03 19:00:00", "length": 1800.0, "newWords": -20, "novelWords": 680, "noteWords": 355, "idleTime": 50 }, { "date": "2021-02-04 19:00:00", "length": 1800.0, "newWords": 40, "novelWords": 700, "noteWords": 375, "idleTime": 60 }, { "date": "2021-02-05 19:00:00", "length": 1800.0, "newWords": -400, "novelWords": 500, "noteWords": 175, "idleTime": 70 }, { "date": "2021-02-06 19:00:00", "length": 1800.0, "newWords": 200, "novelWords": 600, "noteWords": 275, "idleTime": 80 }, { "date": "2021-02-07 19:00:00", "length": 1800.0, "newWords": 0, "novelWords": 600, "noteWords": 275, "idleTime": 90 }] # Group by Day qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton) qtbot.wait(stepDelay) assert sessLog._saveData(sessLog.FMT_JSON) qtbot.wait(stepDelay) jsonStats = os.path.join(fncDir, "sessionStats.json") with open(jsonStats, mode="r", encoding="utf-8") as inFile: jsonData = json.load(inFile) assert sessLog.listBox.topLevelItem(0).text( sessLog.C_COUNT) == "{:n}".format(1) assert sessLog.listBox.topLevelItem(1).text( sessLog.C_COUNT) == "{:n}".format(-200) assert sessLog.listBox.topLevelItem(2).text( sessLog.C_COUNT) == "{:n}".format(180) assert sessLog.listBox.topLevelItem(3).text( sessLog.C_COUNT) == "{:n}".format(-20) assert sessLog.listBox.topLevelItem(4).text( sessLog.C_COUNT) == "{:n}".format(40) assert sessLog.listBox.topLevelItem(5).text( sessLog.C_COUNT) == "{:n}".format(-400) assert sessLog.listBox.topLevelItem(6).text( sessLog.C_COUNT) == "{:n}".format(200) assert sessLog.listBox.topLevelItem(7).text( sessLog.C_COUNT) == "{:n}".format(0) assert jsonData == [{ "date": "2021-01-31", "length": 1800.0, "newWords": 1, "novelWords": 700, "noteWords": 375, "idleTime": 0 }, { "date": "2021-02-01", "length": 3600.0, "newWords": -200, "novelWords": 600, "noteWords": 275, "idleTime": 30 }, { "date": "2021-02-02", "length": 3600.0, "newWords": 180, "novelWords": 690, "noteWords": 365, "idleTime": 70 }, { "date": "2021-02-03", "length": 1800.0, "newWords": -20, "novelWords": 680, "noteWords": 355, "idleTime": 50 }, { "date": "2021-02-04", "length": 1800.0, "newWords": 40, "novelWords": 700, "noteWords": 375, "idleTime": 60 }, { "date": "2021-02-05", "length": 1800.0, "newWords": -400, "novelWords": 500, "noteWords": 175, "idleTime": 70 }, { "date": "2021-02-06", "length": 1800.0, "newWords": 200, "novelWords": 600, "noteWords": 275, "idleTime": 80 }, { "date": "2021-02-07", "length": 1800.0, "newWords": 0, "novelWords": 600, "noteWords": 275, "idleTime": 90 }] # IOError # ======= monkeypatch.setattr("builtins.open", causeOSError) assert not sessLog._loadLogFile() assert not sessLog._saveData(sessLog.FMT_CSV) # qtbot.stopForInteraction() sessLog._doClose() assert nwGUI.closeProject() qtbot.wait(stepDelay)
def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj): """Test the split document tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) # Create a new project nwGUI.theProject.projTree.setSeed(42) assert nwGUI.newProject({"projPath": fncProj}) is True # Handles for new objects hNovelRoot = "73475cb40a568" hChapterDir = "31489056e0916" hToSplit = "1a6562590ef19" hPartition = "41cfc0d1f2d12" hChapterOne = "2858dcd1057d3" hSceneOne = "2fca346db6561" hSceneTwo = "02d20bbd7e394" hSceneThree = "7688b6ef52555" hSceneFour = "c837649cce43f" hSceneFive = "6208ef0f7750c" # Add Project Content monkeypatch.setattr(GuiItemEditor, "exec_", lambda *a: QDialog.Accepted) nwGUI.switchFocus(nwWidget.TREE) nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hNovelRoot).setSelected(True) nwGUI.treeView.newTreeItem(nwItemType.FILE, None) assert nwGUI.saveProject() is True assert nwGUI.closeProject() is True tPartition = "# Nantucket" tChapterOne = "## Chapter One\n\n% Chapter one comment" tSceneOne = "### Scene One\n\nThere once was a man from Nantucket" tSceneTwo = "### Scene Two\n\nWho kept all his cash in a bucket." tSceneThree = "### Scene Three\n\n\tBut his daughter, named Nan, \n\tRan away with a man" tSceneFour = "### Scene Four\n\nAnd as for the bucket, Nantucket." tSceneFive = "#### The End\n\nend" tToSplit = ( f"{tPartition}\n\n{tChapterOne}\n\n" f"{tSceneOne}\n\n{tSceneTwo}\n\n" f"{tSceneThree}\n\n{tSceneFour}\n\n" f"{tSceneFive}\n\n" ) contentDir = os.path.join(fncProj, "content") writeFile(os.path.join(contentDir, hToSplit+".nwd"), tToSplit) assert nwGUI.openProject(fncProj) is True # Open the Split tool nwGUI.switchFocus(nwWidget.TREE) nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hToSplit).setSelected(True) monkeypatch.setattr(GuiDocSplit, "exec_", lambda *a: None) nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000) nwSplit = getGuiItem("GuiDocSplit") assert isinstance(nwSplit, GuiDocSplit) nwSplit.show() qtbot.wait(50) # Populate List # ============= nwSplit.listBox.clear() assert nwSplit.listBox.count() == 0 # No item selected nwSplit.sourceItem = None nwGUI.treeView.clearSelection() assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Non-existing item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) nwSplit.sourceItem = None nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hToSplit).setSelected(True) assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Select a non-file nwSplit.sourceItem = None nwGUI.treeView.clearSelection() nwGUI.treeView._getTreeItem(hChapterDir).setSelected(True) assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Error when reading documents with monkeypatch.context() as mp: mp.setattr(NWDoc, "readDocument", lambda *a: None) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Read properly, and check split levels # Level 1 nwSplit.splitLevel.setCurrentIndex(0) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 1 # Level 2 nwSplit.splitLevel.setCurrentIndex(1) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 2 # Level 3 nwSplit.splitLevel.setCurrentIndex(2) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 6 # Level 4 nwSplit.splitLevel.setCurrentIndex(3) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 7 # Split Document # ============== # Test a proper split first with monkeypatch.context() as mp: mp.setattr(GuiDocSplit, "_doClose", lambda *a: None) assert nwSplit._doSplit() is True assert nwGUI.saveProject() assert readFile(os.path.join(contentDir, hPartition+".nwd")) == ( "%%%%~name: Nantucket\n" "%%%%~path: 031b4af5197ec/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" ) % (hPartition, tPartition) assert readFile(os.path.join(contentDir, hChapterOne+".nwd")) == ( "%%%%~name: Chapter One\n" "%%%%~path: 031b4af5197ec/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" ) % (hChapterOne, tChapterOne) assert readFile(os.path.join(contentDir, hSceneOne+".nwd")) == ( "%%%%~name: Scene One\n" "%%%%~path: 031b4af5197ec/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" ) % (hSceneOne, tSceneOne) assert readFile(os.path.join(contentDir, hSceneTwo+".nwd")) == ( "%%%%~name: Scene Two\n" "%%%%~path: 031b4af5197ec/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" ) % (hSceneTwo, tSceneTwo) assert readFile(os.path.join(contentDir, hSceneThree+".nwd")) == ( "%%%%~name: Scene Three\n" "%%%%~path: 031b4af5197ec/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" ) % (hSceneThree, tSceneThree) assert readFile(os.path.join(contentDir, hSceneFour+".nwd")) == ( "%%%%~name: Scene Four\n" "%%%%~path: 031b4af5197ec/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" ) % (hSceneFour, tSceneFour) assert readFile(os.path.join(contentDir, hSceneFive+".nwd")) == ( "%%%%~name: The End\n" "%%%%~path: 031b4af5197ec/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n" ) % (hSceneFive, tSceneFive) # OS error with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert nwSplit._doSplit() is False # Select to not split with monkeypatch.context() as mp: mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No) assert nwSplit._doSplit() is False # Block folder creation by returning that the folder has a depth # of 50 items in the tree with monkeypatch.context() as mp: mp.setattr(NWTree, "getItemPath", lambda *a: [""]*50) assert nwSplit._doSplit() is False # Clear the list nwSplit.listBox.clear() assert nwSplit._doSplit() is False # Can't find sourcv item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) assert nwSplit._doSplit() is False # No source item set nwSplit.sourceItem = None assert nwSplit._doSplit() is False # Close nwSplit._doClose()
def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): """Test the split document tool. """ # Block message box monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True)) # Create a new project buildTestProject(nwGUI, fncProj) # Handles for new objects hNovelRoot = "0000000000008" hChapterDir = "000000000000d" hToSplit = "0000000000010" hNewFolder = "0000000000021" hPartition = "0000000000022" hChapterOne = "0000000000023" hSceneOne = "0000000000024" hSceneTwo = "0000000000025" hSceneThree = "0000000000026" hSceneFour = "0000000000027" hSceneFive = "0000000000028" # Add Project Content nwGUI.switchFocus(nwWidget.TREE) nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hNovelRoot).setSelected(True) nwGUI.projView.projTree.newTreeItem(nwItemType.FILE) assert nwGUI.saveProject() is True assert nwGUI.closeProject() is True tPartition = "# Nantucket" tChapterOne = "## Chapter One\n\n% Chapter one comment" tSceneOne = "### Scene One\n\nThere once was a man from Nantucket" tSceneTwo = "### Scene Two\n\nWho kept all his cash in a bucket." tSceneThree = "### Scene Three\n\n\tBut his daughter, named Nan, \n\tRan away with a man" tSceneFour = "### Scene Four\n\nAnd as for the bucket, Nantucket." tSceneFive = "#### The End\n\nend" tToSplit = (f"{tPartition}\n\n{tChapterOne}\n\n" f"{tSceneOne}\n\n{tSceneTwo}\n\n" f"{tSceneThree}\n\n{tSceneFour}\n\n" f"{tSceneFive}\n\n") contentDir = os.path.join(fncProj, "content") writeFile(os.path.join(contentDir, hToSplit + ".nwd"), tToSplit) assert nwGUI.openProject(fncProj) is True # Open the Split tool nwGUI.switchFocus(nwWidget.TREE) nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hToSplit).setSelected(True) monkeypatch.setattr(GuiDocSplit, "exec_", lambda *a: None) nwGUI.mainMenu.aSplitDoc.activate(QAction.Trigger) qtbot.waitUntil(lambda: getGuiItem("GuiDocSplit") is not None, timeout=1000) nwSplit = getGuiItem("GuiDocSplit") assert isinstance(nwSplit, GuiDocSplit) nwSplit.show() qtbot.wait(50) # Populate List # ============= nwSplit.listBox.clear() assert nwSplit.listBox.count() == 0 # No item selected nwSplit.sourceItem = None nwGUI.projView.projTree.clearSelection() assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Non-existing item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) nwSplit.sourceItem = None nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hToSplit).setSelected(True) assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Select a non-file nwSplit.sourceItem = None nwGUI.projView.projTree.clearSelection() nwGUI.projView.projTree._getTreeItem(hChapterDir).setSelected(True) assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Error when reading documents with monkeypatch.context() as mp: mp.setattr(NWDoc, "readDocument", lambda *a: None) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is False assert nwSplit.listBox.count() == 0 # Read properly, and check split levels # Level 1 nwSplit.splitLevel.setCurrentIndex(0) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 1 # Level 2 nwSplit.splitLevel.setCurrentIndex(1) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 2 # Level 3 nwSplit.splitLevel.setCurrentIndex(2) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 6 # Level 4 nwSplit.splitLevel.setCurrentIndex(3) nwSplit.sourceItem = hToSplit assert nwSplit._populateList() is True assert nwSplit.listBox.count() == 7 # Split Document # ============== # Test a proper split first with monkeypatch.context() as mp: mp.setattr(GuiDocSplit, "_doClose", lambda *a: None) assert nwSplit._doSplit() is True assert nwGUI.saveProject() assert readFile(os.path.join( contentDir, hPartition + ".nwd")) == ("%%%%~name: Nantucket\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n") % (hNewFolder, hPartition, tPartition) assert readFile(os.path.join( contentDir, hChapterOne + ".nwd")) == ("%%%%~name: Chapter One\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n") % (hNewFolder, hChapterOne, tChapterOne) assert readFile(os.path.join( contentDir, hSceneOne + ".nwd")) == ("%%%%~name: Scene One\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n") % (hNewFolder, hSceneOne, tSceneOne) assert readFile(os.path.join( contentDir, hSceneTwo + ".nwd")) == ("%%%%~name: Scene Two\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n") % (hNewFolder, hSceneTwo, tSceneTwo) assert readFile(os.path.join( contentDir, hSceneThree + ".nwd")) == ("%%%%~name: Scene Three\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n") % (hNewFolder, hSceneThree, tSceneThree) assert readFile(os.path.join( contentDir, hSceneFour + ".nwd")) == ("%%%%~name: Scene Four\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n") % (hNewFolder, hSceneFour, tSceneFour) assert readFile(os.path.join( contentDir, hSceneFive + ".nwd")) == ("%%%%~name: The End\n" "%%%%~path: %s/%s\n" "%%%%~kind: NOVEL/DOCUMENT\n" "%s\n\n") % (hNewFolder, hSceneFive, tSceneFive) # OS error with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) assert nwSplit._doSplit() is False # Select to not split with monkeypatch.context() as mp: mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No) assert nwSplit._doSplit() is False # Clear the list nwSplit.listBox.clear() assert nwSplit._doSplit() is False # Can't find sourcv item with monkeypatch.context() as mp: mp.setattr(NWTree, "__getitem__", lambda *a: None) assert nwSplit._doSplit() is False # No source item set nwSplit.sourceItem = None assert nwSplit._doSplit() is False # Close nwSplit._doClose()