mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-28 06:41:43 +00:00
Email report (#11)
* Demo email report implementation * improved ssl mode * correct default option spelling and more fields to be hidden for not extended reports
This commit is contained in:
@ -15,7 +15,7 @@ def test_finalize(application: Application, mocker: MockerFixture) -> None:
|
||||
report_mock = mocker.patch("ahriman.application.application.Application.report")
|
||||
sync_mock = mocker.patch("ahriman.application.application.Application.sync")
|
||||
|
||||
application._finalize()
|
||||
application._finalize([])
|
||||
report_mock.assert_called_once()
|
||||
sync_mock.assert_called_once()
|
||||
|
||||
@ -218,7 +218,7 @@ def test_report(application: Application, mocker: MockerFixture) -> None:
|
||||
must generate report
|
||||
"""
|
||||
executor_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_report")
|
||||
application.report([])
|
||||
application.report([], [])
|
||||
executor_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -279,7 +279,7 @@ def test_sync(application: Application, mocker: MockerFixture) -> None:
|
||||
must sync to remote
|
||||
"""
|
||||
executor_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_sync")
|
||||
application.sync([])
|
||||
application.sync([], [])
|
||||
executor_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -292,6 +292,7 @@ def test_update(application: Application, package_ahriman: Package, mocker: Mock
|
||||
|
||||
mocker.patch("ahriman.core.tree.Tree.load", return_value=tree)
|
||||
mocker.patch("ahriman.core.repository.repository.Repository.packages_built", return_value=[])
|
||||
mocker.patch("ahriman.models.package.Package.load", return_value=package_ahriman)
|
||||
build_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_build", return_value=paths)
|
||||
update_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_update")
|
||||
finalize_mock = mocker.patch("ahriman.application.application.Application._finalize")
|
||||
@ -299,4 +300,4 @@ def test_update(application: Application, package_ahriman: Package, mocker: Mock
|
||||
application.update([package_ahriman])
|
||||
build_mock.assert_called_once()
|
||||
update_mock.assert_has_calls([mock.call([]), mock.call(paths)])
|
||||
finalize_mock.assert_has_calls([mock.call(), mock.call()])
|
||||
finalize_mock.assert_has_calls([mock.call([]), mock.call([package_ahriman])])
|
||||
|
105
tests/ahriman/core/report/test_email.py
Normal file
105
tests/ahriman/core/report/test_email.py
Normal file
@ -0,0 +1,105 @@
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.report.email import Email
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
def test_send(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must send an email with attachment
|
||||
"""
|
||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report._send("a text", {"attachment.html": "an attachment"})
|
||||
smtp_mock.return_value.starttls.assert_not_called()
|
||||
smtp_mock.return_value.login.assert_not_called()
|
||||
smtp_mock.return_value.sendmail.assert_called_once()
|
||||
smtp_mock.return_value.quit.assert_called_once()
|
||||
|
||||
|
||||
def test_send_auth(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must send an email with attachment with auth
|
||||
"""
|
||||
configuration.set("email", "user", "username")
|
||||
configuration.set("email", "password", "password")
|
||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report._send("a text", {"attachment.html": "an attachment"})
|
||||
smtp_mock.return_value.login.assert_called_once()
|
||||
|
||||
|
||||
def test_send_auth_no_password(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must send an email with attachment without auth if no password supplied
|
||||
"""
|
||||
configuration.set("email", "user", "username")
|
||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report._send("a text", {"attachment.html": "an attachment"})
|
||||
smtp_mock.return_value.login.assert_not_called()
|
||||
|
||||
|
||||
def test_send_auth_no_user(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must send an email with attachment without auth if no user supplied
|
||||
"""
|
||||
configuration.set("email", "password", "password")
|
||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report._send("a text", {"attachment.html": "an attachment"})
|
||||
smtp_mock.return_value.login.assert_not_called()
|
||||
|
||||
|
||||
def test_send_ssl_tls(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must send an email with attachment with ssl/tls
|
||||
"""
|
||||
configuration.set("email", "ssl", "ssl")
|
||||
smtp_mock = mocker.patch("smtplib.SMTP_SSL")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report._send("a text", {"attachment.html": "an attachment"})
|
||||
smtp_mock.return_value.starttls.assert_not_called()
|
||||
smtp_mock.return_value.login.assert_not_called()
|
||||
smtp_mock.return_value.sendmail.assert_called_once()
|
||||
smtp_mock.return_value.quit.assert_called_once()
|
||||
|
||||
|
||||
def test_send_starttls(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must send an email with attachment with starttls
|
||||
"""
|
||||
configuration.set("email", "ssl", "starttls")
|
||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report._send("a text", {"attachment.html": "an attachment"})
|
||||
smtp_mock.return_value.starttls.assert_called_once()
|
||||
|
||||
|
||||
def test_generate(configuration: Configuration, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate report
|
||||
"""
|
||||
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report.generate([package_ahriman], [])
|
||||
send_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_generate_with_built(configuration: Configuration, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate report with built packages
|
||||
"""
|
||||
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
|
||||
|
||||
report = Email("x86_64", configuration)
|
||||
report.generate([package_ahriman], [package_ahriman])
|
||||
send_mock.assert_called_once()
|
@ -12,5 +12,5 @@ def test_generate(configuration: Configuration, package_ahriman: Package, mocker
|
||||
write_mock = mocker.patch("pathlib.Path.write_text")
|
||||
|
||||
report = HTML("x86_64", configuration)
|
||||
report.generate([package_ahriman])
|
||||
report.generate([package_ahriman], [])
|
||||
write_mock.assert_called_once()
|
||||
|
19
tests/ahriman/core/report/test_jinja_tempalte.py
Normal file
19
tests/ahriman/core/report/test_jinja_tempalte.py
Normal file
@ -0,0 +1,19 @@
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.report.jinja_template import JinjaTemplate
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
def test_generate(configuration: Configuration, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must generate html report
|
||||
"""
|
||||
report = JinjaTemplate("html", configuration)
|
||||
assert report.make_html([package_ahriman], extended_report=False)
|
||||
|
||||
|
||||
def test_generate_extended(configuration: Configuration, package_ahriman: Package) -> None:
|
||||
"""
|
||||
must generate extended html report
|
||||
"""
|
||||
report = JinjaTemplate("html", configuration)
|
||||
assert report.make_html([package_ahriman], extended_report=True)
|
@ -15,7 +15,7 @@ def test_report_failure(configuration: Configuration, mocker: MockerFixture) ->
|
||||
"""
|
||||
mocker.patch("ahriman.core.report.html.HTML.generate", side_effect=Exception())
|
||||
with pytest.raises(ReportFailed):
|
||||
Report.load("x86_64", configuration, ReportSettings.HTML.name).run(Path("path"))
|
||||
Report.load("x86_64", configuration, ReportSettings.HTML.name).run(Path("path"), [])
|
||||
|
||||
|
||||
def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
@ -24,7 +24,16 @@ def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> No
|
||||
"""
|
||||
mocker.patch("ahriman.models.report_settings.ReportSettings.from_option", return_value=ReportSettings.Disabled)
|
||||
report_mock = mocker.patch("ahriman.core.report.report.Report.generate")
|
||||
Report.load("x86_64", configuration, ReportSettings.Disabled.name).run(Path("path"))
|
||||
Report.load("x86_64", configuration, ReportSettings.Disabled.name).run(Path("path"), [])
|
||||
report_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_report_email(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must generate email report
|
||||
"""
|
||||
report_mock = mocker.patch("ahriman.core.report.email.Email.generate")
|
||||
Report.load("x86_64", configuration, ReportSettings.Email.name).run(Path("path"), [])
|
||||
report_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -33,5 +42,5 @@ def test_report_html(configuration: Configuration, mocker: MockerFixture) -> Non
|
||||
must generate html report
|
||||
"""
|
||||
report_mock = mocker.patch("ahriman.core.report.html.HTML.generate")
|
||||
Report.load("x86_64", configuration, ReportSettings.HTML.name).run(Path("path"))
|
||||
Report.load("x86_64", configuration, ReportSettings.HTML.name).run(Path("path"), [])
|
||||
report_mock.assert_called_once()
|
||||
|
@ -133,7 +133,7 @@ def test_process_report(executor: Executor, package_ahriman: Package, mocker: Mo
|
||||
mocker.patch("ahriman.core.report.report.Report.load", return_value=Report("x86_64", executor.configuration))
|
||||
report_mock = mocker.patch("ahriman.core.report.report.Report.run")
|
||||
|
||||
executor.process_report(["dummy"])
|
||||
executor.process_report(["dummy"], [])
|
||||
report_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -143,7 +143,7 @@ def test_process_report_auto(executor: Executor, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
configuration_getlist_mock = mocker.patch("ahriman.core.configuration.Configuration.getlist")
|
||||
|
||||
executor.process_report(None)
|
||||
executor.process_report(None, [])
|
||||
configuration_getlist_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -154,7 +154,7 @@ def test_process_upload(executor: Executor, mocker: MockerFixture) -> None:
|
||||
mocker.patch("ahriman.core.upload.upload.Upload.load", return_value=Upload("x86_64", executor.configuration))
|
||||
upload_mock = mocker.patch("ahriman.core.upload.upload.Upload.run")
|
||||
|
||||
executor.process_sync(["dummy"])
|
||||
executor.process_sync(["dummy"], [])
|
||||
upload_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -164,7 +164,7 @@ def test_process_upload_auto(executor: Executor, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
configuration_getlist_mock = mocker.patch("ahriman.core.configuration.Configuration.getlist")
|
||||
|
||||
executor.process_sync(None)
|
||||
executor.process_sync(None, [])
|
||||
configuration_getlist_mock.assert_called_once()
|
||||
|
||||
|
||||
|
@ -12,5 +12,5 @@ def test_sync(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
check_output_mock = mocker.patch("ahriman.core.upload.rsync.Rsync._check_output")
|
||||
|
||||
upload = Rsync("x86_64", configuration)
|
||||
upload.sync(Path("path"))
|
||||
upload.sync(Path("path"), [])
|
||||
check_output_mock.assert_called_once()
|
||||
|
@ -12,5 +12,5 @@ def test_sync(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
check_output_mock = mocker.patch("ahriman.core.upload.s3.S3._check_output")
|
||||
|
||||
upload = S3("x86_64", configuration)
|
||||
upload.sync(Path("path"))
|
||||
upload.sync(Path("path"), [])
|
||||
check_output_mock.assert_called_once()
|
||||
|
@ -15,7 +15,7 @@ def test_upload_failure(configuration: Configuration, mocker: MockerFixture) ->
|
||||
"""
|
||||
mocker.patch("ahriman.core.upload.rsync.Rsync.sync", side_effect=Exception())
|
||||
with pytest.raises(SyncFailed):
|
||||
Upload.load("x86_64", configuration, UploadSettings.Rsync.name).run(Path("path"))
|
||||
Upload.load("x86_64", configuration, UploadSettings.Rsync.name).run(Path("path"), [])
|
||||
|
||||
|
||||
def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
@ -24,7 +24,7 @@ def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> No
|
||||
"""
|
||||
mocker.patch("ahriman.models.upload_settings.UploadSettings.from_option", return_value=UploadSettings.Disabled)
|
||||
upload_mock = mocker.patch("ahriman.core.upload.upload.Upload.sync")
|
||||
Upload.load("x86_64", configuration, UploadSettings.Disabled.name).run(Path("path"))
|
||||
Upload.load("x86_64", configuration, UploadSettings.Disabled.name).run(Path("path"), [])
|
||||
upload_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ def test_upload_rsync(configuration: Configuration, mocker: MockerFixture) -> No
|
||||
must upload via rsync
|
||||
"""
|
||||
upload_mock = mocker.patch("ahriman.core.upload.rsync.Rsync.sync")
|
||||
Upload.load("x86_64", configuration, UploadSettings.Rsync.name).run(Path("path"))
|
||||
Upload.load("x86_64", configuration, UploadSettings.Rsync.name).run(Path("path"), [])
|
||||
upload_mock.assert_called_once()
|
||||
|
||||
|
||||
@ -42,5 +42,5 @@ def test_upload_s3(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
must upload via s3
|
||||
"""
|
||||
upload_mock = mocker.patch("ahriman.core.upload.s3.S3.sync")
|
||||
Upload.load("x86_64", configuration, UploadSettings.S3.name).run(Path("path"))
|
||||
Upload.load("x86_64", configuration, UploadSettings.S3.name).run(Path("path"), [])
|
||||
upload_mock.assert_called_once()
|
||||
|
@ -18,3 +18,6 @@ def test_from_option_valid() -> None:
|
||||
"""
|
||||
assert ReportSettings.from_option("html") == ReportSettings.HTML
|
||||
assert ReportSettings.from_option("HTML") == ReportSettings.HTML
|
||||
|
||||
assert ReportSettings.from_option("email") == ReportSettings.Email
|
||||
assert ReportSettings.from_option("EmAil") == ReportSettings.Email
|
||||
|
21
tests/ahriman/models/test_smtp_settings.py
Normal file
21
tests/ahriman/models/test_smtp_settings.py
Normal file
@ -0,0 +1,21 @@
|
||||
from ahriman.models.smtp_ssl_settings import SmtpSSLSettings
|
||||
|
||||
|
||||
def test_from_option_invalid() -> None:
|
||||
"""
|
||||
must return disabled value on invalid option
|
||||
"""
|
||||
assert SmtpSSLSettings.from_option("invalid") == SmtpSSLSettings.Disabled
|
||||
|
||||
|
||||
def test_from_option_valid() -> None:
|
||||
"""
|
||||
must return value from valid options
|
||||
"""
|
||||
assert SmtpSSLSettings.from_option("ssl") == SmtpSSLSettings.SSL
|
||||
assert SmtpSSLSettings.from_option("SSL") == SmtpSSLSettings.SSL
|
||||
assert SmtpSSLSettings.from_option("ssl/tls") == SmtpSSLSettings.SSL
|
||||
assert SmtpSSLSettings.from_option("SSL/TLS") == SmtpSSLSettings.SSL
|
||||
|
||||
assert SmtpSSLSettings.from_option("starttls") == SmtpSSLSettings.STARTTLS
|
||||
assert SmtpSSLSettings.from_option("STARTTLS") == SmtpSSLSettings.STARTTLS
|
@ -25,6 +25,14 @@ target =
|
||||
[report]
|
||||
target =
|
||||
|
||||
[email]
|
||||
host = 0.0.0.0
|
||||
link_path =
|
||||
port = 587
|
||||
receivers = mail@example.com
|
||||
sender = mail@example.com
|
||||
template_path = ../web/templates/repo-index.jinja2
|
||||
|
||||
[html]
|
||||
path =
|
||||
homepage =
|
||||
|
Reference in New Issue
Block a user