mirror of
https://github.com/chatmail/relay.git
synced 2026-05-10 16:04:37 +00:00
making it work
This commit is contained in:
@@ -36,7 +36,7 @@ DNS domain name (FQDN), for example `chat.example.org`.
|
|||||||
3. Create chatmail configuration file `chatmail.ini`:
|
3. Create chatmail configuration file `chatmail.ini`:
|
||||||
|
|
||||||
```
|
```
|
||||||
cmdeploy genconfig chatmail.ini CHATMAIL_DOMAIN
|
cmdeploy init chatmail.ini CHATMAIL_DOMAIN
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Deploy to the remote chatmail server, pointing to the chatmail config file:
|
4. Deploy to the remote chatmail server, pointing to the chatmail config file:
|
||||||
|
|||||||
@@ -1,41 +1,25 @@
|
|||||||
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
import iniconfig
|
import iniconfig
|
||||||
|
|
||||||
system_mailname_path = Path("/etc/mailname")
|
|
||||||
|
|
||||||
|
def read_config(inipath):
|
||||||
def read_config(inipath, mailname=None):
|
cfg = iniconfig.IniConfig(inipath)
|
||||||
if mailname is None:
|
return Config(inipath, params=cfg.sections["params"])
|
||||||
with open(system_mailname_path) as f:
|
|
||||||
mailname = f.read().strip()
|
|
||||||
|
|
||||||
ini = iniconfig.IniConfig(inipath)
|
|
||||||
privacy = {}
|
|
||||||
for section in ini:
|
|
||||||
if section.name.startswith("privacy:"):
|
|
||||||
domain = section["domain"]
|
|
||||||
if fnmatch(mailname, domain):
|
|
||||||
privacy = section
|
|
||||||
break
|
|
||||||
|
|
||||||
return Config(inipath, mailname, privacy, params=ini.sections["params"])
|
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
def __init__(self, inipath, mailname, privacy, params):
|
def __init__(self, inipath, params):
|
||||||
self._inipath = inipath
|
self._inipath = inipath
|
||||||
self.mailname = mailname
|
self.mailname = params["mailname"]
|
||||||
self.privacy_postal = privacy.get("privacy_postal")
|
|
||||||
self.privacy_mail = privacy.get("privacy_mail")
|
|
||||||
self.privacy_pdo = privacy.get("privacy_pdo")
|
|
||||||
self.privacy_supervisor = privacy.get("privacy_supervisor")
|
|
||||||
self.max_user_send_per_minute = int(params["max_user_send_per_minute"])
|
self.max_user_send_per_minute = int(params["max_user_send_per_minute"])
|
||||||
self.filtermail_smtp_port = int(params["filtermail_smtp_port"])
|
self.filtermail_smtp_port = int(params["filtermail_smtp_port"])
|
||||||
self.postfix_reinject_port = int(params["postfix_reinject_port"])
|
self.postfix_reinject_port = int(params["postfix_reinject_port"])
|
||||||
self.passthrough_recipients = params["passthrough_recipients"].split()
|
self.passthrough_recipients = params["passthrough_recipients"].split()
|
||||||
|
self.privacy_postal = params.get("privacy_postal")
|
||||||
|
self.privacy_mail = params.get("privacy_mail")
|
||||||
|
self.privacy_pdo = params.get("privacy_pdo")
|
||||||
|
self.privacy_supervisor = params.get("privacy_supervisor")
|
||||||
|
|
||||||
def _getbytefile(self):
|
def _getbytefile(self):
|
||||||
return open(self._inipath, "rb")
|
return open(self._inipath, "rb")
|
||||||
|
|||||||
@@ -127,7 +127,10 @@ class BeforeQueueHandler:
|
|||||||
|
|
||||||
is_outgoing = recipient_domain != envelope_from_domain
|
is_outgoing = recipient_domain != envelope_from_domain
|
||||||
if is_outgoing and not mail_encrypted:
|
if is_outgoing and not mail_encrypted:
|
||||||
is_securejoin = message.get("secure-join") in ["vc-request", "vg-request"]
|
is_securejoin = message.get("secure-join") in [
|
||||||
|
"vc-request",
|
||||||
|
"vg-request",
|
||||||
|
]
|
||||||
if not is_securejoin:
|
if not is_securejoin:
|
||||||
return f"500 Invalid unencrypted mail to <{recipient}>"
|
return f"500 Invalid unencrypted mail to <{recipient}>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools>=45"]
|
requires = ["setuptools>=68"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
@@ -12,9 +12,13 @@ dependencies = [
|
|||||||
"markdown",
|
"markdown",
|
||||||
"pytest",
|
"pytest",
|
||||||
"setuptools>=68",
|
"setuptools>=68",
|
||||||
|
"termcolor",
|
||||||
"tox",
|
"tox",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
cmdeploy = "deploy_chatmail.cmdeploy:main"
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
addopts = "-v -ra --strict-markers"
|
addopts = "-v -ra --strict-markers"
|
||||||
|
|
||||||
|
|||||||
132
deploy-chatmail/src/deploy_chatmail/cmdeploy.py
Normal file
132
deploy-chatmail/src/deploy_chatmail/cmdeploy.py
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
"""
|
||||||
|
Provides the `cmdeploy` entry point function,
|
||||||
|
along with command line option and subcommand parsing.
|
||||||
|
"""
|
||||||
|
import importlib.resources
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import iniconfig
|
||||||
|
|
||||||
|
from termcolor import colored
|
||||||
|
from chatmaild.config import read_config
|
||||||
|
|
||||||
|
|
||||||
|
class Out:
|
||||||
|
"""Convenience print output printer providing coloring."""
|
||||||
|
|
||||||
|
def red(self, msg):
|
||||||
|
print(colored(msg, "red"))
|
||||||
|
|
||||||
|
def green(self, msg):
|
||||||
|
print(colored(msg, "green"))
|
||||||
|
|
||||||
|
def __call__(self, msg, red=False, green=False):
|
||||||
|
color = "red" if red else ("green" if green else None)
|
||||||
|
print(colored(msg, color))
|
||||||
|
|
||||||
|
|
||||||
|
description = """\
|
||||||
|
Setup your chatmail server configuration and
|
||||||
|
deploy it via SSH to your remote location.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def add_config_option(parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--config",
|
||||||
|
dest="chatmail_ini",
|
||||||
|
action="store",
|
||||||
|
default=Path("chatmail.ini"),
|
||||||
|
type=Path,
|
||||||
|
help="path to the chatmail.ini file",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def add_subcommand(subparsers, func):
|
||||||
|
name = func.__name__
|
||||||
|
assert name.endswith("_cmd")
|
||||||
|
name = name[:-4]
|
||||||
|
doc = func.__doc__.strip()
|
||||||
|
p = subparsers.add_parser(name, description=doc, help=doc)
|
||||||
|
p.set_defaults(func=func)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def get_parser():
|
||||||
|
"""Return an ArgumentParser for the 'cmdeploy' CLI."""
|
||||||
|
parser = argparse.ArgumentParser(description=description)
|
||||||
|
subparsers = parser.add_subparsers(
|
||||||
|
title="subcommands",
|
||||||
|
)
|
||||||
|
|
||||||
|
init_parser = add_subcommand(subparsers, init_cmd)
|
||||||
|
add_config_option(init_parser)
|
||||||
|
init_parser.add_argument(
|
||||||
|
"chatmail_domain",
|
||||||
|
action="store",
|
||||||
|
help="fully qualified DNS domain name for your chatmail instance",
|
||||||
|
)
|
||||||
|
|
||||||
|
install_parser = add_subcommand(subparsers, install_cmd)
|
||||||
|
add_config_option(install_parser)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def write_initial_config(inipath, mailname, out):
|
||||||
|
inidir = importlib.resources.files(__package__).joinpath("ini")
|
||||||
|
content = inidir.joinpath("chatmail.ini.f").read_text().format(mailname=mailname)
|
||||||
|
if mailname.endswith(".testrun.org"):
|
||||||
|
override_inipath = inidir.joinpath("override-testrun.ini")
|
||||||
|
privacy = iniconfig.IniConfig(override_inipath)["privacy"]
|
||||||
|
lines = []
|
||||||
|
for line in content.split("\n"):
|
||||||
|
for key, value in privacy.items():
|
||||||
|
value_lines = value.strip().split("\n")
|
||||||
|
if not line.startswith(f"{key} =") or not value_lines:
|
||||||
|
continue
|
||||||
|
if len(value_lines) == 1:
|
||||||
|
lines.append(f"{key} = {value}")
|
||||||
|
else:
|
||||||
|
lines.append(f"{key} =")
|
||||||
|
for vl in value_lines:
|
||||||
|
lines.append(f" {vl}")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
lines.append(line)
|
||||||
|
content = "\n".join(lines)
|
||||||
|
|
||||||
|
inipath.write_text(content)
|
||||||
|
out(f"written {inipath} for chatmail domain {mailname}")
|
||||||
|
|
||||||
|
|
||||||
|
def init_cmd(args, out):
|
||||||
|
"""Initialize chatmail config file."""
|
||||||
|
if args.chatmail_ini.exists():
|
||||||
|
out.red(f"Path exists, not modifying: {args.xdcget_ini}")
|
||||||
|
raise SystemExit(1)
|
||||||
|
write_initial_config(args.chatmail_ini, args.chatmail_domain, out)
|
||||||
|
|
||||||
|
|
||||||
|
def install_cmd(args, out):
|
||||||
|
"""Install or update chatmail services on the remote server. """
|
||||||
|
try:
|
||||||
|
config = read_config(args.chatmail_ini)
|
||||||
|
except Exception as ex:
|
||||||
|
out.red(ex)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
XXX
|
||||||
|
|
||||||
|
|
||||||
|
def main(args=None):
|
||||||
|
"""Provide main entry point for 'xdcget' CLI invocation."""
|
||||||
|
parser = get_parser()
|
||||||
|
args = parser.parse_args(args=args)
|
||||||
|
if not hasattr(args, "func"):
|
||||||
|
return parser.parse_args(["-h"])
|
||||||
|
out = Out()
|
||||||
|
args.func(args, out)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
# mail domain (MUST be set to fully qualified chat mail domain)
|
# mail domain (MUST be set to fully qualified chat mail domain)
|
||||||
domain = {mailname}
|
mailname = {mailname}
|
||||||
|
|
||||||
#
|
#
|
||||||
# If you only do private test deploys, you don't need to modify any settings below
|
# If you only do private test deploys, you don't need to modify any settings below
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
|
|
||||||
mailname = {mailname}
|
[privacy]
|
||||||
max_user_send_per_minute = 60
|
|
||||||
passthrough_recipients = privacy@testrun.org xstore@testrun.org
|
|
||||||
|
|
||||||
filtermail_smtp_port = 10080
|
passthrough_recipients = privacy@testrun.org
|
||||||
postfix_reinject_port = 10025
|
|
||||||
|
|
||||||
privacy_postal =
|
privacy_postal =
|
||||||
Merlinux GmbH, Represented by the managing director H. Krekel,
|
Merlinux GmbH, Represented by the managing director H. Krekel,
|
||||||
Reichgrafen Str. 20, 79102 Freiburg, Germany
|
Reichgrafen Str. 20, 79102 Freiburg, Germany
|
||||||
|
|
||||||
privacy_mail = delta-privacy@merlinux.eu
|
privacy_mail = privacy@testrun.org
|
||||||
privacy_pdo =
|
privacy_pdo =
|
||||||
Prof. Dr. Fabian Schmieder, lexICT UG (limited), Ostfeldstr. 49, 30559 Hannover.
|
Prof. Dr. Fabian Schmieder, lexICT UG (limited), Ostfeldstr. 49, 30559 Hannover.
|
||||||
You can contact him at *delta-privacy@merlinux.eu* (Keyword: DPO)
|
You can contact him at *delta-privacy@merlinux.eu* (Keyword: DPO)
|
||||||
@@ -2,87 +2,27 @@ from chatmaild.config import read_config
|
|||||||
import chatmaild.config
|
import chatmaild.config
|
||||||
|
|
||||||
|
|
||||||
def test_read_config_without_mailname(tmp_path, create_ini, monkeypatch):
|
def test_read_config_basic(make_config):
|
||||||
mailname_path = tmp_path.joinpath("mailname")
|
config = make_config("chat.example.org")
|
||||||
mailname_path.write_text("something.example.org")
|
assert config.mailname == "chat.example.org"
|
||||||
monkeypatch.setattr(chatmaild.config, "system_mailname_path", mailname_path)
|
assert not config.privacy_supervisor and not config.privacy_mail
|
||||||
|
assert not config.privacy_pdo and not config.privacy_postal
|
||||||
|
|
||||||
inipath = create_ini(
|
inipath = config._inipath
|
||||||
"""
|
inipath.write_text(inipath.read_text().replace("60", "37"))
|
||||||
[params]
|
|
||||||
max_user_send_per_minute = 40
|
|
||||||
filtermail_smtp_port = 9875
|
|
||||||
postfix_reinject_port = 9999
|
|
||||||
passthrough_recipients =
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
config = read_config(inipath)
|
config = read_config(inipath)
|
||||||
assert config.mailname == "something.example.org"
|
assert config.max_user_send_per_minute == 37
|
||||||
|
assert config.mailname == "chat.example.org"
|
||||||
|
|
||||||
|
|
||||||
def test_read_config_without_privacy_policy(tmp_path, create_ini):
|
def test_read_config_testrun(make_config):
|
||||||
inipath = create_ini(
|
config = make_config("something.testrun.org")
|
||||||
"""
|
|
||||||
[params]
|
|
||||||
max_user_send_per_minute = 40
|
|
||||||
filtermail_smtp_port = 9875
|
|
||||||
postfix_reinject_port = 9999
|
|
||||||
passthrough_recipients =
|
|
||||||
|
|
||||||
[privacy:testrun]
|
|
||||||
domain = *.example.org
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
config = read_config(inipath, "something.example.org")
|
|
||||||
assert config.mailname == "something.example.org"
|
|
||||||
assert config.max_user_send_per_minute == 40
|
|
||||||
assert config.filtermail_smtp_port == 9875
|
|
||||||
assert config.postfix_reinject_port == 9999
|
|
||||||
assert config.passthrough_recipients == []
|
|
||||||
assert not config.privacy_postal
|
|
||||||
assert not config.privacy_mail
|
|
||||||
assert not config.privacy_pdo
|
|
||||||
assert not config.privacy_supervisor
|
|
||||||
|
|
||||||
|
|
||||||
def test_read_config(create_ini):
|
|
||||||
inipath = create_ini(
|
|
||||||
"""
|
|
||||||
[params]
|
|
||||||
max_user_send_per_minute = 40
|
|
||||||
filtermail_smtp_port = 10080
|
|
||||||
postfix_reinject_port = 10025
|
|
||||||
passthrough_recipients = x@example.org y@example.org
|
|
||||||
|
|
||||||
[privacy:testrun]
|
|
||||||
domain = *.testrun.org
|
|
||||||
|
|
||||||
privacy_postal =
|
|
||||||
Postal Ltd
|
|
||||||
|
|
||||||
privacy_mail = privacy@merlinux.eu
|
|
||||||
|
|
||||||
privacy_pdo =
|
|
||||||
Postal PDO
|
|
||||||
You can contact him at *delta-privacy@merlinux.eu* (Keyword: DPO)
|
|
||||||
|
|
||||||
privacy_supervisor =
|
|
||||||
line1
|
|
||||||
line2 with space
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
config = read_config(inipath, "something.testrun.org")
|
|
||||||
|
|
||||||
assert config.mailname == "something.testrun.org"
|
assert config.mailname == "something.testrun.org"
|
||||||
|
assert len(config.privacy_postal.split("\n")) > 1
|
||||||
|
assert len(config.privacy_supervisor.split("\n")) > 1
|
||||||
|
assert len(config.privacy_pdo.split("\n")) > 1
|
||||||
|
assert config.privacy_mail == "privacy@testrun.org"
|
||||||
assert config.filtermail_smtp_port == 10080
|
assert config.filtermail_smtp_port == 10080
|
||||||
assert config.postfix_reinject_port == 10025
|
assert config.postfix_reinject_port == 10025
|
||||||
assert config.passthrough_recipients == ["x@example.org", "y@example.org"]
|
assert config.max_user_send_per_minute == 60
|
||||||
assert config.privacy_postal == "Postal Ltd"
|
assert config.passthrough_recipients
|
||||||
assert config.privacy_mail == "privacy@merlinux.eu"
|
|
||||||
lines = config.privacy_pdo.split("\n")
|
|
||||||
assert lines[0] == "Postal PDO"
|
|
||||||
assert lines[1].startswith("You can ")
|
|
||||||
lines = config.privacy_supervisor.split("\n")
|
|
||||||
assert lines[0] == "line1"
|
|
||||||
assert lines[1] == "line2 with space"
|
|
||||||
|
|||||||
@@ -39,13 +39,6 @@ def pytest_runtest_setup(item):
|
|||||||
pytest.skip("skipping slow test, use --slow to run")
|
pytest.skip("skipping slow test, use --slow to run")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def inipath():
|
|
||||||
dpath = importlib.resources.files("chatmaild")
|
|
||||||
inipath = dpath.joinpath("../../../chatmail.ini").resolve()
|
|
||||||
assert inipath.exists()
|
|
||||||
return inipath
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def maildomain():
|
def maildomain():
|
||||||
@@ -415,13 +408,13 @@ class CMUser:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def create_ini(tmp_path, inipath):
|
def make_config(tmp_path):
|
||||||
def create_ini_func(source=None):
|
from deploy_chatmail.cmdeploy import main
|
||||||
if source is None:
|
from chatmaild.config import read_config
|
||||||
source = inipath.read_text()
|
inipath = tmp_path.joinpath("chatmail.ini")
|
||||||
p = tmp_path.joinpath("chatmail.ini")
|
|
||||||
assert not p.exists(), p
|
|
||||||
p.write_text(textwrap.dedent(source))
|
|
||||||
return p
|
|
||||||
|
|
||||||
return create_ini_func
|
def make_conf(mailname):
|
||||||
|
main(["init", "--config", str(inipath), mailname])
|
||||||
|
return read_config(inipath)
|
||||||
|
|
||||||
|
return make_conf
|
||||||
|
|||||||
104
tests/test_cmdeploy.py
Normal file
104
tests/test_cmdeploy.py
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import pytest
|
||||||
|
from deploy_chatmail.cmdeploy import get_parser, main
|
||||||
|
from chatmaild.config import read_config
|
||||||
|
|
||||||
|
|
||||||
|
class TestCmdline:
|
||||||
|
def test_parser(self, capsys):
|
||||||
|
parser = get_parser()
|
||||||
|
parser.parse_args([])
|
||||||
|
init = parser.parse_args(["init", "chat.example.org"])
|
||||||
|
update = parser.parse_args(["install"])
|
||||||
|
assert init and update
|
||||||
|
|
||||||
|
def test_init(self, tmpdir):
|
||||||
|
tmpdir.chdir()
|
||||||
|
main(["init", "chat.example.org"])
|
||||||
|
inipath = tmpdir.join("chatmail.ini")
|
||||||
|
config = read_config(inipath.strpath)
|
||||||
|
assert config.mailname == "chat.example.org"
|
||||||
|
|
||||||
|
def test_no_args_description(self, capsys):
|
||||||
|
with pytest.raises(SystemExit) as excinfo:
|
||||||
|
main([])
|
||||||
|
assert excinfo.value.code == 0
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert "Collect webxdc" in out
|
||||||
|
assert " init " in out and "Initialize config" in out
|
||||||
|
|
||||||
|
def test_version(self, capsys):
|
||||||
|
with pytest.raises(SystemExit) as excinfo:
|
||||||
|
main(["--version"])
|
||||||
|
assert excinfo.value.code == 0
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert out.strip() == xdcget.__version__
|
||||||
|
|
||||||
|
def test_init_not_overwrite(self, tmpdir):
|
||||||
|
tmpdir.chdir()
|
||||||
|
main(["init"])
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
main(["init"])
|
||||||
|
|
||||||
|
def test_update_from_different_dir(self, config_example1, tmp_path):
|
||||||
|
p = tmp_path.joinpath("somewhere")
|
||||||
|
p.mkdir()
|
||||||
|
os.chdir(p)
|
||||||
|
main(["--config", "../xdcget.ini", "update"])
|
||||||
|
|
||||||
|
def test_prune_index(self, iniconfig):
|
||||||
|
iniconfig.add_source(
|
||||||
|
app_id="webxdc-poll",
|
||||||
|
source_code_url="https://codeberg.org/webxdc/poll",
|
||||||
|
)
|
||||||
|
iniconfig.add_lock_entry(
|
||||||
|
app_id="webxdc-poll",
|
||||||
|
name="Poll",
|
||||||
|
tag_name="v1.0.1",
|
||||||
|
url="https://codeberg.org/attachments/d53543bd-d805-4aba-926d-88eefc7a9eef",
|
||||||
|
date="2023-07-05T20:30:48Z",
|
||||||
|
cache_relname="webxdc-poll-v1.0.1.xdc",
|
||||||
|
)
|
||||||
|
iniconfig.add_lock_entry(
|
||||||
|
app_id="webxdc-checklist",
|
||||||
|
name="Checklist",
|
||||||
|
tag_name="v0.0.2",
|
||||||
|
url="https://codeberg.org/attachments/65d05b8d-a97c-4fb6-a534-e308c382f874",
|
||||||
|
date="2023-07-07T18:05:19Z",
|
||||||
|
cache_relname="webxdc-checklist-v0.0.2.xdc",
|
||||||
|
)
|
||||||
|
|
||||||
|
config = iniconfig.create()
|
||||||
|
assert "webxdc-poll" in config.index_path.read_text()
|
||||||
|
assert "webxdc-checklist" in config.index_path.read_text()
|
||||||
|
main(["update"])
|
||||||
|
assert "webxdc-poll" in config.index_path.read_text()
|
||||||
|
assert "webxdc-checklist" not in config.index_path.read_text()
|
||||||
|
|
||||||
|
def test_update_empty(self, iniconfig):
|
||||||
|
iniconfig.create()
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
main(["update"])
|
||||||
|
|
||||||
|
def test_update_no_network(self, capfd, config_example1, monkeypatch):
|
||||||
|
main(["update"])
|
||||||
|
p = config_example1.export_dir.joinpath("xdcget.lock")
|
||||||
|
assert p.exists()
|
||||||
|
assert len(p.read_text()) > 50
|
||||||
|
monkeypatch.delattr(sys.modules["requests"], "get")
|
||||||
|
main(["update", "--offline"])
|
||||||
|
|
||||||
|
def test_export_json(self, capfd, config_example1, monkeypatch):
|
||||||
|
main(["update"])
|
||||||
|
p = config_example1.export_dir.joinpath("xdcget-lock.json")
|
||||||
|
assert p.exists()
|
||||||
|
with p.open() as f:
|
||||||
|
app_list = json.load(f)
|
||||||
|
assert len(app_list) == 2
|
||||||
|
checklist, poll = app_list
|
||||||
|
p = config_example1.export_dir.joinpath(checklist["icon_relname"])
|
||||||
|
assert p.exists() and "icon" in p.name
|
||||||
|
p = config_example1.export_dir.joinpath(poll["icon_relname"])
|
||||||
|
assert p.exists() and "icon" in p.name
|
||||||
Reference in New Issue
Block a user