1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
import pytest
from PyQt6 import QtCore
from PyQt6.QtWidgets import QMessageBox
import vorta.views
from vorta.views.main_window import MainWindow
from vorta.views.source_tab import SourceTab
@pytest.fixture()
def source_env(qapp, qtbot, monkeypatch, choose_file_dialog):
"""
Handles common setup and teardown for unit tests involving the source tab.
"""
main: MainWindow = qapp.main_window
tab: SourceTab = main.sourceTab
main.tabWidget.setCurrentIndex(1)
qtbot.waitUntil(lambda: tab.sourceFilesWidget.rowCount() == 1, timeout=2000)
monkeypatch.setattr(vorta.views.source_tab, "choose_file_dialog", choose_file_dialog)
yield main, tab
# Wait for directory sizing to finish
qtbot.waitUntil(lambda: len(qapp.main_window.sourceTab.updateThreads) == 0, timeout=2000)
@pytest.mark.skip(reason="prone to failure due to background thread")
def test_source_add_remove(qapp, qtbot, monkeypatch, mocker, source_env):
"""
Tests adding and removing source to ensure expected behavior.
"""
main, tab = source_env
mocker.patch.object(QMessageBox, "exec") # prevent QMessageBox from stopping test
# test adding a folder with os access
mocker.patch('os.access', return_value=True)
tab.source_add(want_folder=True)
qtbot.waitUntil(lambda: tab.sourceFilesWidget.rowCount() == 2, **pytest._wait_defaults)
assert tab.sourceFilesWidget.rowCount() == 2
# test adding a folder without os access
mocker.patch('os.access', return_value=False)
tab.source_add(want_folder=True)
assert tab.sourceFilesWidget.rowCount() == 2
# test removing a folder
tab.sourceFilesWidget.selectRow(1)
qtbot.mouseClick(tab.removeButton, QtCore.Qt.MouseButton.LeftButton)
qtbot.waitUntil(lambda: tab.sourceFilesWidget.rowCount() == 1, **pytest._wait_defaults)
assert tab.sourceFilesWidget.rowCount() == 1
@pytest.mark.skip(reason="prone to failure due to background thread")
@pytest.mark.parametrize(
"path, valid",
[
(__file__, True), # valid path
("test", False), # invalid path
(f"file://{__file__}", True), # valid - normal path with prefix that will be stripped
(f"file://{__file__}\n{__file__}", True), # valid - two files separated by new line
(f"file://{__file__}{__file__}", False), # invalid - no new line separating file names
],
)
def test_valid_and_invalid_source_paths(qapp, qtbot, mocker, source_env, path, valid):
"""
Valid paths will be added as a source.
Invalid paths will trigger an alert and not be added as a source.
"""
main, tab = source_env
mock_clipboard = mocker.Mock()
mock_clipboard.text.return_value = path
mocker.patch.object(vorta.views.source_tab.QApplication, 'clipboard', return_value=mock_clipboard)
mocker.patch.object(QMessageBox, "exec") # prevent QMessageBox from stopping test
tab.paste_text()
if valid:
assert not hasattr(tab, '_msg')
qtbot.waitUntil(lambda: tab.sourceFilesWidget.rowCount() == 2, **pytest._wait_defaults)
assert tab.sourceFilesWidget.rowCount() == 2
else:
qtbot.waitUntil(lambda: hasattr(tab, "_msg"), **pytest._wait_defaults)
assert tab._msg.text().startswith("Some of your sources are invalid")
assert tab.sourceFilesWidget.rowCount() == 1
@pytest.mark.skip(reason="prone to failure due to background thread")
def test_sources_update(qapp, qtbot, mocker, source_env):
"""
Tests the source update button in the source tab
"""
main, tab = source_env
update_path_info_spy = mocker.spy(tab, "update_path_info")
# test that `update_path_info()` has been called for each source path
qtbot.mouseClick(tab.updateButton, QtCore.Qt.MouseButton.LeftButton)
assert tab.sourceFilesWidget.rowCount() == 1
assert update_path_info_spy.call_count == 1
# add a new source and reset mock
tab.source_add(want_folder=True)
qtbot.waitUntil(lambda: tab.sourceFilesWidget.rowCount() == 2, **pytest._wait_defaults)
update_path_info_spy.reset_mock()
# retest that `update_path_info()` has been called for each source path
qtbot.mouseClick(tab.updateButton, QtCore.Qt.MouseButton.LeftButton)
assert tab.sourceFilesWidget.rowCount() == 2
assert update_path_info_spy.call_count == 2
@pytest.mark.skip(reason="prone to failure due to background thread")
def test_source_copy(qapp, qtbot, monkeypatch, mocker, source_env):
"""
Test source_copy() with and without an index passed.
If no index is passed, it should copy the first selected source
"""
main, tab = source_env
mock_clipboard = mocker.patch.object(qapp.clipboard(), "setMimeData")
tab.source_add(want_folder=True)
qtbot.waitUntil(lambda: tab.sourceFilesWidget.rowCount() == 2, **pytest._wait_defaults)
tab.sourceFilesWidget.selectRow(0)
tab.source_copy()
assert mock_clipboard.call_count == 1
source = mock_clipboard.call_args[0][0] # retrieves the QMimeData() object used in method call
assert source.text() == "/tmp"
index = tab.sourceFilesWidget.model().index(1, 0)
tab.source_copy(index)
assert mock_clipboard.call_count == 2
source = mock_clipboard.call_args[0][0] # retrieves the QMimeData() object used in method call
assert source.text() == "/tmp/another"
|