diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-12 11:27:51 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-12 11:27:51 +0200 |
| commit | a0b5c51ff335e36761312c9c9c75156dc33d3913 (patch) | |
| tree | 9f62a8f369ec09b2ac3899ddaa89a762287d6f3a /test_mailrules.py | |
| parent | 89a41a913d5f0fbf385b70643cba26d64c9ed81c (diff) | |
| download | mailctl-a0b5c51ff335e36761312c9c9c75156dc33d3913.tar.gz mailctl-a0b5c51ff335e36761312c9c9c75156dc33d3913.zip | |
feat(rules): load a shared tagging-rule store
The rules that tag incoming mail live in a notmuch post-new hook as
hand-written shell. This is the first piece of moving them into a JSON
store that both this tool and qtmaildir read.
A rule carries no scope: the hook supplies tag:new, a dry run supplies
nothing. Unknown fields are kept per rule so the format belongs to
neither tool.
Diffstat (limited to 'test_mailrules.py')
| -rwxr-xr-x | test_mailrules.py | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/test_mailrules.py b/test_mailrules.py new file mode 100755 index 0000000..dd491e9 --- /dev/null +++ b/test_mailrules.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2026 Danilo M. <danix@danix.xyz> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +"""Self-checks for mailrules.py, the shared tagging-rule store. + +The risk in this file is the format, not the notmuch calls: a rule that +silently loses a field on save, or one that sorts into the wrong stage, +mis-tags real mail on the next sync and does it quietly. + +Run: ./test_mailrules.py +""" + +import json +import tempfile +from pathlib import Path + +import mailrules + + +def write_rules(tmp, payload): + path = Path(tmp) / "rules.json" + path.write_text(json.dumps(payload)) + return path + + +def test_loads_a_rule(): + with tempfile.TemporaryDirectory() as tmp: + path = write_rules(tmp, { + "version": 1, + "rules": [ + { + "id": "notify-forge", + "stage": 50, + "enabled": True, + "add": ["notify/forge"], + "remove": [], + "query": "from:notifications@example.com", + "note": "All repositories, not one project.", + } + ], + }) + store = mailrules.load(path) + assert store.warnings == [], store.warnings + assert len(store.rules) == 1 + rule = store.rules[0] + assert rule.id == "notify-forge" + assert rule.stage == 50 + assert rule.enabled is True + assert rule.add == ["notify/forge"] + assert rule.remove == [] + assert rule.query == "from:notifications@example.com" + assert rule.note == "All repositories, not one project." + + +def test_defaults_are_applied(): + """stage, enabled, remove and note are all optional in the file.""" + with tempfile.TemporaryDirectory() as tmp: + path = write_rules(tmp, { + "version": 1, + "rules": [{"id": "minimal", "add": ["x"], + "query": "from:someone@example.com"}], + }) + store = mailrules.load(path) + assert store.warnings == [], store.warnings + rule = store.rules[0] + assert rule.stage == 50 + assert rule.enabled is True + assert rule.remove == [] + assert rule.note == "" + + +def run_all(): + for name, fn in sorted(globals().items()): + if name.startswith("test_") and callable(fn): + fn() + print(f"ok {name}") + + +if __name__ == "__main__": + run_all() + print("\nall passed") |
