mirror of
https://github.com/samschott/maestral.git
synced 2024-09-22 03:18:33 +03:00
244 lines
7.4 KiB
Python
244 lines
7.4 KiB
Python
import logging
|
|
|
|
from click.testing import CliRunner
|
|
|
|
from maestral.main import Maestral
|
|
from maestral.cli import main
|
|
from maestral.autostart import AutoStart
|
|
from maestral.notify import level_number_to_name, level_name_to_number
|
|
from maestral.daemon import MaestralProxy, start_maestral_daemon_process, Start
|
|
from maestral.logging import scoped_logger
|
|
from maestral.utils.appdirs import get_log_path
|
|
|
|
|
|
TEST_TIMEOUT = 60
|
|
|
|
|
|
def test_help() -> None:
|
|
"""Test help output without args and with --help arg."""
|
|
runner = CliRunner()
|
|
|
|
result_no_arg = runner.invoke(main)
|
|
result_help_arg = runner.invoke(main, ["--help"])
|
|
|
|
assert result_no_arg.exit_code == 0, result_no_arg.output
|
|
assert result_no_arg.output.startswith("Usage: main [OPTIONS] COMMAND [ARGS]")
|
|
|
|
assert result_no_arg.output == result_help_arg.output
|
|
|
|
|
|
def test_invalid_config() -> None:
|
|
"""Test failure of commands that require an existing config file"""
|
|
|
|
for command in [
|
|
("stop",),
|
|
("pause",),
|
|
("resume",),
|
|
("auth", "status"),
|
|
("auth", "unlink"),
|
|
("sharelink", "create"),
|
|
("sharelink", "list"),
|
|
("sharelink", "revoke"),
|
|
("status",),
|
|
("filestatus",),
|
|
("activity",),
|
|
("history",),
|
|
("ls",),
|
|
("autostart",),
|
|
("excluded", "add"),
|
|
("excluded", "list"),
|
|
("excluded", "remove"),
|
|
("notify", "level"),
|
|
("notify", "snooze"),
|
|
("move-dir",),
|
|
("rebuild-index",),
|
|
("revs",),
|
|
("diff",),
|
|
("restore",),
|
|
("log", "level"),
|
|
("log", "clear"),
|
|
("log", "show"),
|
|
("config", "get", "path"),
|
|
("config", "set", "path"),
|
|
("config", "show"),
|
|
]:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, [*command, "-c", "non-existent-config"])
|
|
|
|
assert result.exit_code == 1, command
|
|
assert (
|
|
result.output == "! Configuration 'non-existent-config' does not exist. "
|
|
"Use 'maestral config-files' to list all configurations.\n"
|
|
)
|
|
|
|
|
|
def test_start_already_running(config_name: str) -> None:
|
|
res = start_maestral_daemon_process(config_name, timeout=TEST_TIMEOUT)
|
|
|
|
assert res is Start.Ok
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["start", "-c", config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "already running" in result.output
|
|
|
|
|
|
def test_stop(config_name: str) -> None:
|
|
res = start_maestral_daemon_process(config_name, timeout=TEST_TIMEOUT)
|
|
assert res is Start.Ok
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["stop", "-c", config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
|
|
def test_filestatus(m: Maestral) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["filestatus", "/usr", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert result.output == "unwatched\n"
|
|
|
|
result = runner.invoke(main, ["filestatus", "/invalid-dir", "-c", m.config_name])
|
|
|
|
# the exception will be already raised by click's argument check
|
|
assert result.exit_code == 2
|
|
assert isinstance(result.exception, SystemExit)
|
|
assert "'/invalid-dir' does not exist" in result.output
|
|
|
|
|
|
def test_autostart(m: Maestral) -> None:
|
|
autostart = AutoStart(m.config_name)
|
|
autostart.disable()
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["autostart", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "disabled" in result.output
|
|
|
|
result = runner.invoke(main, ["autostart", "-Y", "-c", m.config_name])
|
|
|
|
if autostart.implementation:
|
|
if result.exit_code == 0:
|
|
assert "Enabled" in result.output
|
|
assert autostart.enabled
|
|
else:
|
|
# TODO: be more specific here
|
|
assert result.exception is not None
|
|
else:
|
|
assert "not supported" in result.output
|
|
assert not autostart.enabled
|
|
|
|
result = runner.invoke(main, ["autostart", "-N", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "Disabled" in result.output
|
|
assert not autostart.enabled
|
|
|
|
|
|
def test_excluded_list(m: Maestral) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["excluded", "list", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert result.output == "No excluded files or folders.\n"
|
|
|
|
|
|
def test_notify_level(config_name: str) -> None:
|
|
start_maestral_daemon_process(config_name, timeout=TEST_TIMEOUT)
|
|
m = MaestralProxy(config_name)
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["notify", "level", "-c", m.config_name])
|
|
|
|
level_name = level_number_to_name(m.notification_level)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert level_name in result.output
|
|
|
|
level_name = "SYNCISSUE"
|
|
level_number = level_name_to_number(level_name)
|
|
result = runner.invoke(main, ["notify", "level", level_name, "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert level_name in result.output
|
|
assert m.notification_level == level_number
|
|
|
|
result = runner.invoke(main, ["notify", "level", "INVALID", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 2
|
|
assert isinstance(result.exception, SystemExit)
|
|
|
|
|
|
def test_notify_snooze(config_name: str) -> None:
|
|
start_maestral_daemon_process(config_name, timeout=TEST_TIMEOUT)
|
|
m = MaestralProxy(config_name)
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["notify", "snooze", "20", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert 0 < m.notification_snooze <= 20
|
|
|
|
result = runner.invoke(main, ["notify", "snooze", "0", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert m.notification_snooze == 0
|
|
|
|
|
|
def test_log_level(m: Maestral) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["log", "level", "-c", m.config_name])
|
|
|
|
level_name = logging.getLevelName(m.log_level)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert level_name in result.output
|
|
|
|
result = runner.invoke(main, ["log", "level", "DEBUG", "-c", m.config_name])
|
|
assert result.exit_code == 0, result.output
|
|
assert "DEBUG" in result.output
|
|
|
|
result = runner.invoke(main, ["notify", "level", "INVALID", "-c", m.config_name])
|
|
assert result.exit_code == 2
|
|
assert isinstance(result.exception, SystemExit)
|
|
|
|
|
|
def test_log_show(m: Maestral) -> None:
|
|
# log a message
|
|
logger = scoped_logger("maestral", m.config_name)
|
|
logger.info("Hello from pytest!")
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["log", "show", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "Hello from pytest!" in result.output
|
|
|
|
|
|
def test_log_clear(m: Maestral) -> None:
|
|
# log a message
|
|
logger = scoped_logger("maestral", m.config_name)
|
|
logger.info("Hello from pytest!")
|
|
runner = CliRunner()
|
|
result = runner.invoke(main, ["log", "show", "-c", m.config_name])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "Hello from pytest!" in result.output
|
|
|
|
# Stop connection helper to prevent spurious log messages.
|
|
m.manager._connection_helper_running = False
|
|
m.manager.connection_helper.join()
|
|
|
|
# clear the logs
|
|
result = runner.invoke(main, ["log", "clear", "-c", m.config_name])
|
|
assert result.exit_code == 0, result.output
|
|
|
|
logfile = get_log_path("maestral", f"{m.config_name}.log")
|
|
with open(logfile) as f:
|
|
log_content = f.read()
|
|
|
|
assert log_content == ""
|