Beispiel #1
0
    def test_continue_after_skip_exists(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test entry addition continues after skipping over existing entry.

        Regression test against #83

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        with tempfile.NamedTemporaryFile("w") as file:
            with open(EXAMPLE_DUPLICATE_ENTRY_BIB, "r", encoding="utf-8") as existing:
                file.writelines(existing.readlines())
            file.writelines(["@article{dummy,\nauthor = {Dummy},\n}"])
            file.flush()
            AddCommand().execute(["--skip-existing", "-b", file.name])
        assert (
            "cobib.commands.add",
            30,
            "You tried to add a new entry 'einstein' which already exists!",
        ) in caplog.record_tuples
        assert (
            "cobib.commands.add",
            30,
            "Please use `cobib edit einstein` instead!",
        ) in caplog.record_tuples
        assert (
            "cobib.database.database",
            10,
            "Updating entry dummy",
        ) in caplog.record_tuples
Beispiel #2
0
    def test_command(self, setup: Any, more_args: List[str], entry_kwargs: Dict[str, Any]) -> None:
        """Test the command itself.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            more_args: additional arguments to be passed to the command.
            entry_kwargs: the expected contents of the resulting `Entry`.
        """
        git = setup.get("git", False)

        try:
            label = more_args[more_args.index("-l") + 1]
        except ValueError:
            label = "example_multi_file_entry"
        args = ["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB] + more_args

        AddCommand().execute(args)

        assert Database()[label]

        if entry_kwargs or label != "example_multi_file_entry":
            self._assert_entry(label, **entry_kwargs)
        else:
            # only when we don't use extra arguments the files will match
            self._assert(EXAMPLE_MULTI_FILE_ENTRY_YAML)

        if git:
            # assert the git commit message
            # Note: we do not assert the arguments, because they depend on the available parsers
            self.assert_git_commit_message("add", None)
Beispiel #3
0
    def test_tui(self, setup: Any) -> None:
        """Test the TUI access of the command.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
        """
        def assertion(screen, logs, **kwargs):  # type: ignore
            # check that the undone entry has actually been present in the buffer before
            assert (
                "cobib.tui.buffer",
                10,
                "Appending string to text buffer: example_multi_file_entry",
            ) in logs
            # but is no longer there, now
            assert "example_multi_file_entry" not in screen.display[1]

            expected_log = [
                ("cobib.commands.undo", 10,
                 "Undo command triggered from TUI."),
                ("cobib.commands.undo", 10, "Starting Undo command."),
                ("cobib.commands.undo", 10, "Obtaining git log."),
            ]
            # we only assert the first three messages because the following ones will contain always
            # changing commit SHAs
            assert [log for log in logs
                    if log[0] == "cobib.commands.undo"][0:3] == expected_log

        AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
        self.run_tui("u", assertion, {})
Beispiel #4
0
    def test_add_skip_download(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test adding a new entry and skipping the automatic download.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        path = RelPath("/tmp/Cao2018.pdf")
        try:
            args = ["-a", "1812.09976", "--skip-download"]

            AddCommand().execute(args)

            if (
                "cobib.parsers.arxiv",
                logging.ERROR,
                "An Exception occurred while trying to query the arXiv ID: 1812.09976.",
            ) in caplog.record_tuples:
                pytest.skip("The requests API encountered an error. Skipping test.")

            entry = Database()["Cao2018"]
            assert entry.label == "Cao2018"
            assert entry.data["archivePrefix"] == "arXiv"
            assert entry.data["arxivid"].startswith("1812.09976")
            assert "_download" not in entry.data.keys()
            assert not os.path.exists(path.path)
        finally:
            try:
                os.remove(path.path)
            except FileNotFoundError:
                pass
Beispiel #5
0
    def test_disambiguate_label(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test label disambiguation if the provided one already exists.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        git = setup.get("git", False)

        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB])

        assert (
            "cobib.commands.add",
            30,
            "You tried to add a new entry 'einstein' which already exists!",
        ) in caplog.record_tuples
        assert (
            "cobib.commands.add",
            30,
            "The label will be disambiguated based on the configuration option: "
            "config.database.format.label_suffix",
        ) in caplog.record_tuples

        assert Database()["einstein_a"]

        if git:
            # assert the git commit message
            self.assert_git_commit_message("add", None)
Beispiel #6
0
    def test_skipping_undone_commits(self, setup: Any,
                                     caplog: pytest.LogCaptureFixture) -> None:
        """Test skipping already undone commits.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
        AddCommand().execute(["-b", get_resource("example_entry.bib")])
        UndoCommand().execute([])
        caplog.clear()

        UndoCommand().execute([])
        self._assert()
        assert "Storing undone commit" in caplog.record_tuples[4][2]
        assert "Skipping" in caplog.record_tuples[6][2]
Beispiel #7
0
    def test_command(
        self, setup: Any, expected_exit: bool, caplog: pytest.LogCaptureFixture
    ) -> None:
        """Test the command itself.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            expected_exit: whether to expect an early exit.
            caplog: the built-in pytest fixture.
        """
        git = setup.get("git", False)

        if not git:
            RedoCommand().execute([])
            for (source, level, message) in caplog.record_tuples:
                if ("cobib.commands.redo", logging.ERROR) == (
                    source,
                    level,
                ) and "git-tracking" in message:
                    break
            else:
                pytest.fail("No Error logged from RedoCommand.")
        elif expected_exit:
            # Regression test against #65
            AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
            with pytest.raises(SystemExit):
                RedoCommand().execute([])
            for (source, level, message) in caplog.record_tuples:
                if ("cobib.commands.redo", logging.WARNING) == (
                    source,
                    level,
                ) and "Could not find a commit to redo." in message:
                    break
            else:
                pytest.fail("No Error logged from UndoCommand.")
        else:
            AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
            UndoCommand().execute([])

            if Database().get("example_multi_file_entry", None) is not None:
                pytest.skip("UndoCommand failed. No point in attempting Redo.")

            RedoCommand().execute([])

            self._assert()
Beispiel #8
0
def assert_delete(screen):
    """Asserts entry is deleted.

    This also ensures it is added again after successful deletion.
    """
    try:
        assert f"CoBib v{version} - 3 Entries" in screen.display[0]
        assert not any("dummy_entry_for_scroll_testing" in line for line in screen.display[4:21])
    finally:
        AddCommand().execute(['-b', './test/dummy_scrolling_entry.bib'])
Beispiel #9
0
    def test_event_post_add_command(self, setup: Any) -> None:
        """Tests the PostAddCommand event."""

        @Event.PostAddCommand.subscribe
        def hook(new_entries: Dict[str, Entry]) -> None:
            new_entries["dummy"] = new_entries.pop("einstein_a")

        assert Event.PostAddCommand.validate()

        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB])

        assert "dummy" in Database().keys()
Beispiel #10
0
def setup():
    """Setup."""
    # ensure configuration is empty
    CONFIG.config = {}
    root = os.path.abspath(os.path.dirname(__file__))
    CONFIG.set_config(Path(root + '/../cobib/docs/debug.ini'))
    # NOTE: normally you would never trigger an Add command before reading the database but in this
    # controlled testing scenario we can be certain that this is fine
    AddCommand().execute(['-b', './test/dummy_scrolling_entry.bib'])
    read_database()
    yield setup
    DeleteCommand().execute(['dummy_entry_for_scroll_testing'])
Beispiel #11
0
    def test_event_pre_add_command(self, setup: Any) -> None:
        """Tests the PreAddCommand event."""

        @Event.PreAddCommand.subscribe
        def hook(largs: Namespace) -> None:
            largs.label = "dummy"

        assert Event.PreAddCommand.validate()

        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB])

        assert "dummy" in Database().keys()
Beispiel #12
0
    def test_warning_missing_label(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test warning for missing label and any other input.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        AddCommand().execute([""])
        assert (
            "cobib.commands.add",
            40,
            "Neither an input to parse nor a label for manual creation specified!",
        ) in caplog.record_tuples
Beispiel #13
0
    def test_cmdline(self, setup: Any, monkeypatch: pytest.MonkeyPatch,
                     caplog: pytest.LogCaptureFixture) -> None:
        """Test the command-line access of the command.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            monkeypatch: the built-in pytest fixture.
            caplog: the built-in pytest fixture.
        """
        AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
        self.run_module(monkeypatch, "main", ["cobib", "undo"])

        self._assert()
Beispiel #14
0
def test_tui_open_menu():
    """Test the open prompt menu for multiple associated files."""
    # ensure configuration is empty
    CONFIG.config = {}
    root = os.path.abspath(os.path.dirname(__file__))
    CONFIG.set_config(Path(root + '/../cobib/docs/debug.ini'))
    # NOTE: normally you would never trigger an Add command before reading the database but in this
    # controlled testing scenario we can be certain that this is fine
    AddCommand().execute(['-b', './test/dummy_multi_file_entry.bib'])
    read_database()
    try:
        test_tui(None, 'o', assert_open, {})
    finally:
        DeleteCommand().execute(['dummy_multi_file_entry'])
Beispiel #15
0
    def test_event_post_undo_command(self, setup: Any) -> None:
        """Tests the PostUndoCommand event."""
        @Event.PostUndoCommand.subscribe
        def hook(root: Path, sha: str) -> None:
            print(root)

        assert Event.PostUndoCommand.validate()

        with contextlib.redirect_stdout(StringIO()) as out:
            AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
            UndoCommand().execute([])

            self._assert()

            assert out.getvalue() == f"{self.COBIB_TEST_DIR}\n"
Beispiel #16
0
def test_tui_config_keys(command, key):
    """Test TUI key binding configuration."""
    # ensure configuration is empty
    CONFIG.config = {}
    root = os.path.abspath(os.path.dirname(__file__))
    CONFIG.set_config(Path(root + '/../cobib/docs/debug.ini'))
    # overwrite key binding configuration
    CONFIG.config['KEY_BINDINGS'][command] = key
    # NOTE: normally you would never trigger an Add command before reading the database but in this
    # controlled testing scenario we can be certain that this is fine
    AddCommand().execute(['-b', './test/dummy_scrolling_entry.bib'])
    read_database()
    try:
        test_tui(None, key, assert_show, {})
    finally:
        DeleteCommand().execute(['dummy_entry_for_scroll_testing'])
Beispiel #17
0
    def test_configured_label_default(self, setup: Any) -> None:
        """Test add command when a `label_default` is pre-configured.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
        """
        config.database.format.label_default = "{author.split()[1]}{year}"
        git = setup.get("git", False)

        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB])

        assert Database()["Einstein1905"]

        if git:
            # assert the git commit message
            self.assert_git_commit_message("add", None)
Beispiel #18
0
    def test_add_with_download(
        self,
        folder: Optional[str],
        setup: Any,
        capsys: pytest.CaptureFixture[str],
        caplog: pytest.LogCaptureFixture,
    ) -> None:
        """Test adding a new entry with an associated file automatically downloaded.

        Args:
            folder: the folder for the downloaded file.
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            capsys: the built-in pytest fixture.
            caplog: the built-in pytest fixture.
        """
        path = RelPath(f"{'/tmp' if folder is None else folder}/Cao2018.pdf")
        try:
            # ensure file does not exist yet
            os.remove(path.path)
        except FileNotFoundError:
            pass
        try:
            args = ["-a", "1812.09976"]
            if folder:
                args += ["-p", folder]

            AddCommand().execute(args)

            if (
                "cobib.parsers.arxiv",
                logging.ERROR,
                "An Exception occurred while trying to query the arXiv ID: 1812.09976.",
            ) in caplog.record_tuples:
                pytest.skip("The requests API encountered an error. Skipping test.")

            entry = Database()["Cao2018"]
            assert entry.label == "Cao2018"
            assert entry.data["archivePrefix"] == "arXiv"
            assert entry.data["arxivid"].startswith("1812.09976")
            assert "_download" not in entry.data.keys()
            assert f"Successfully downloaded {path}" in capsys.readouterr().out
            assert os.path.exists(path.path)
        finally:
            try:
                os.remove(path.path)
            except FileNotFoundError:
                pass
Beispiel #19
0
    def test_skip_manual_add_if_exists(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test manual addition is skipped if the label exists already.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        AddCommand().execute(["-l", "einstein"])
        assert (
            "cobib.commands.add",
            30,
            "You tried to add a new entry 'einstein' which already exists!",
        ) in caplog.record_tuples
        assert (
            "cobib.commands.add",
            30,
            "Please use `cobib edit einstein` instead!",
        ) in caplog.record_tuples
Beispiel #20
0
    def test_cmdline(
        self, setup: Any, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture
    ) -> None:
        """Test the command-line access of the command.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            monkeypatch: the built-in pytest fixture.
            caplog: the built-in pytest fixture.
        """
        AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
        UndoCommand().execute([])

        if Database().get("example_multi_file_entry", None) is not None:
            pytest.skip("UndoCommand failed. No point in attempting Redo.")

        self.run_module(monkeypatch, "main", ["cobib", "redo"])

        self._assert()
Beispiel #21
0
    def test_add_new_entry(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test adding a new plain entry.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        AddCommand().execute(["-l", "dummy"])
        assert (
            "cobib.commands.add",
            30,
            "No input to parse. Creating new entry 'dummy' manually.",
        ) in caplog.record_tuples

        with open(config.database.file, "r", encoding="utf-8") as file:
            lines = file.readlines()
            dummy_start = lines.index("dummy:\n")
            assert dummy_start > 0
            assert lines[dummy_start - 1] == "---\n"
            assert lines[dummy_start + 1] == "  ENTRYTYPE: article\n"
            assert lines[dummy_start + 2] == "...\n"
Beispiel #22
0
    def test_event_post_redo_command(self, setup: Any) -> None:
        """Tests the PostRedoCommand event."""

        @Event.PostRedoCommand.subscribe
        def hook(root: Path, sha: str) -> None:
            print(root)

        assert Event.PostRedoCommand.validate()

        with contextlib.redirect_stdout(StringIO()) as out:
            AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
            UndoCommand().execute([])

            if Database().get("example_multi_file_entry", None) is not None:
                pytest.skip("UndoCommand failed. No point in attempting Redo.")

            RedoCommand().execute([])

            self._assert()

            assert out.getvalue() == f"{self.COBIB_TEST_DIR}\n"
Beispiel #23
0
    def test_tui(self, setup: Any) -> None:
        """Test the TUI access of the command.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
        """

        def assertion(screen, logs, **kwargs):  # type: ignore
            assert "example_multi_file_entry" in screen.display[1]

            expected_log = [
                ("cobib.commands.redo", 10, "Redo command triggered from TUI."),
                ("cobib.commands.redo", 10, "Starting Redo command."),
                ("cobib.commands.redo", 10, "Obtaining git log."),
            ]
            # we only assert the first three messages because the following ones will contain always
            # changing commit SHAs
            assert [log for log in logs if log[0] == "cobib.commands.redo"][0:3] == expected_log

        AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
        UndoCommand().execute([])
        self.run_tui("r", assertion, {})
Beispiel #24
0
    def test_overwrite_label(self, setup: Any) -> None:
        """Test add command while specifying a label manually.

        Regression test against #4.

        The duplicate entry has been adapted to also assert the elongation of Journal names.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
        """
        config.utils.journal_abbreviations = [("Annalen der Physik", "Ann. Phys.")]
        git = setup.get("git", False)
        # add potentially duplicate entry
        AddCommand().execute(["-b", EXAMPLE_DUPLICATE_ENTRY_BIB, "--label", "duplicate_resolver"])

        assert Database()["duplicate_resolver"]

        self._assert(EXAMPLE_DUPLICATE_ENTRY_YAML)

        if git:
            # assert the git commit message
            self.assert_git_commit_message("add", None)
Beispiel #25
0
    def test_command(self, setup: Any, expected_exit: bool,
                     caplog: pytest.LogCaptureFixture) -> None:
        """Test the command itself.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            expected_exit: whether to expect an early exit.
            caplog: the built-in pytest fixture.
        """
        git = setup.get("git", False)

        if not git:
            UndoCommand().execute([])
            for (source, level, message) in caplog.record_tuples:
                if ("cobib.commands.undo", logging.ERROR) == (
                        source,
                        level,
                ) and "git-tracking" in message:
                    break
            else:
                pytest.fail("No Error logged from UndoCommand.")
        elif expected_exit:
            # Regression test related to #65
            with pytest.raises(SystemExit):
                UndoCommand().execute([])
            for (source, level, message) in caplog.record_tuples:
                if ("cobib.commands.undo", logging.WARNING) == (
                        source,
                        level,
                ) and "Could not find a commit to undo." in message:
                    break
            else:
                pytest.fail("No Error logged from UndoCommand.")
        else:
            AddCommand().execute(["-b", EXAMPLE_MULTI_FILE_ENTRY_BIB])
            UndoCommand().execute([])

            self._assert()
Beispiel #26
0
    def test_add_with_update(self, setup: Any, caplog: pytest.LogCaptureFixture) -> None:
        """Test update option of AddCommand.

        Args:
            setup: the `tests.commands.command_test.CommandTest.setup` fixture.
            caplog: the built-in pytest fixture.
        """
        git = setup.get("git", False)
        AddCommand().execute(["-a", "1812.09976", "--skip-download"])

        if (
            "cobib.parsers.arxiv",
            logging.ERROR,
            "An Exception occurred while trying to query the arXiv ID: 1812.09976.",
        ) in caplog.record_tuples:
            pytest.skip("The requests API encountered an error. Skipping test.")

        # assert initial state
        entry = Database()["Cao2018"]

        assert entry.data["author"].startswith("Yudong Cao")
        assert entry.data["title"].startswith("Quantum Chemistry in the Age of Quantum Computing")
        assert entry.data["arxivid"].startswith("1812.09976")
        assert entry.data["doi"] == "10.1021/acs.chemrev.8b00803"
        assert entry.data["primaryClass"] == "quant-ph"
        assert entry.data["archivePrefix"] == "arXiv"
        assert entry.data["abstract"] != ""
        assert entry.data["year"] == 2018

        assert "journal" not in entry.data.keys()
        assert "month" not in entry.data.keys()
        assert "number" not in entry.data.keys()
        assert "pages" not in entry.data.keys()
        assert "volume" not in entry.data.keys()

        args = ["-d", "10.1021/acs.chemrev.8b00803", "-l", "Cao2018", "--skip-download", "--update"]
        AddCommand().execute(args)

        if (
            "cobib.parsers.doi",
            logging.ERROR,
            "An Exception occurred while trying to query the DOI: 10.1021/acs.chemrev.8b00803.",
        ) in caplog.record_tuples:
            pytest.skip("The requests API encountered an error. Skipping test.")

        # assert final state
        entry = Database()["Cao2018"]

        assert entry.data["author"].startswith("Yudong Cao")
        assert entry.data["title"].startswith("Quantum Chemistry in the Age of Quantum Computing")
        assert entry.data["arxivid"].startswith("1812.09976")
        assert entry.data["primaryClass"] == "quant-ph"
        assert entry.data["archivePrefix"] == "arXiv"
        assert entry.data["abstract"] != ""

        assert entry.data["journal"] == "Chemical Reviews"
        assert entry.data["doi"] == "10.1021/acs.chemrev.8b00803"
        assert entry.data["month"] == "aug"
        assert entry.data["number"] == 19
        assert entry.data["pages"] == "10856--10915"
        assert entry.data["volume"] == 119
        assert entry.data["year"] == 2019

        if git:
            # assert the git commit message
            # Note: we do not assert the arguments, because they depend on the available parsers
            self.assert_git_commit_message("add", None)