diff options
Diffstat (limited to 'mail-overview/test-mail-notify.sh')
| -rwxr-xr-x | mail-overview/test-mail-notify.sh | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/mail-overview/test-mail-notify.sh b/mail-overview/test-mail-notify.sh new file mode 100755 index 0000000..1c3e01a --- /dev/null +++ b/mail-overview/test-mail-notify.sh @@ -0,0 +1,148 @@ +#!/bin/bash +# +# 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. +# +# The one runnable check for mail-notify.sh. No framework: it sources the +# script as a library and asserts on the pure functions, the ones that take +# text and print text. Nothing here calls notmuch, dunstify or inotify, which +# is why it runs in milliseconds and needs no mail to arrive. +# +# Usage: ./test-mail-notify.sh (exit 0 = all passed) + +set -u + +MAIL_NOTIFY_LIB=1 . "$(dirname "$0")/mail-notify.sh" + +pass=0 +fail=0 + +# Compares two strings and reports. Multi-line values are printed with their +# newlines intact, because half the assertions here are about line structure. +check() { + local name="$1" want="$2" got="$3" + if [[ "$want" == "$got" ]]; then + pass=$((pass + 1)) + else + fail=$((fail + 1)) + printf 'FAIL: %s\n want: %s\n got: %s\n' "$name" "$want" "$got" + fi +} + +check "library guard does not run main" "loaded" "loaded" + +# A config with the two traps in it: a key containing dots, and a folder +# value containing a bracket. Both are real shapes from qtmaildir.conf, with +# placeholder names. +read -r -d '' fixture <<'EOF' +[general] +theme = dark + +[account.simple] +label = Simple +color = #112233 + +[account.provider-first.last] +folder = [Gmail]/Bozze +label = Dotted +color = #445566 + +[account.nolabel] +color = #778899 + +[ui] +label = NotAnAccount +EOF + +check "keys run to the bracket, not the first dot" \ + "simple provider-first.last nolabel" \ + "$(parse_accounts <<<"$fixture" | cut -f1 | tr '\n' ' ' | sed 's/ $//')" + +check "a bracket in a value does not end the section" \ + "Dotted" \ + "$(parse_accounts <<<"$fixture" | awk -F'\t' '$1=="provider-first.last"{print $2}')" + +check "a missing label falls back to the key" \ + "nolabel" \ + "$(parse_accounts <<<"$fixture" | awk -F'\t' '$1=="nolabel"{print $2}')" + +check "a non-account section is not an account" \ + "" \ + "$(parse_accounts <<<"$fixture" | awk -F'\t' '$1=="ui"{print $2}')" + +# The shape notmuch search --format=json actually returns, trimmed to the two +# fields the body uses. +rows_json='[ + {"authors":"Alice Example","subject":"First subject"}, + {"authors":"Bob Example","subject":"Second subject"}, + {"authors":"Carol Example","subject":"Third subject"} +]' + +check "a body lists author and subject per row" \ + "• Alice Example — First subject + +• Bob Example — Second subject + +• Carol Example — Third subject" \ + "$(build_body "$rows_json" 3)" + +check "a batch bigger than the rows shown is elided" \ + "• Alice Example — First subject + +• Bob Example — Second subject + +• Carol Example — Third subject ++7 more" \ + "$(build_body "$rows_json" 10)" + +check "markup characters are escaped, not rendered" \ + "• A & B — <script>" \ + "$(build_body '[{"authors":"A & B","subject":"<script>"}]' 1)" + +check "a missing subject says so rather than printing nothing" \ + "• Alice Example — (no subject)" \ + "$(build_body '[{"authors":"Alice Example","subject":null}]' 1)" + +check "malformed json yields an empty body rather than an error" \ + "" \ + "$(build_body 'not json at all' 1 2>/dev/null)" + +check "a newline in a subject stays on one row" \ + "• Alice Example — line one line two" \ + "$(build_body '[{"authors":"Alice Example","subject":"line one\nline two"}]' 1)" + +# A scratch state file, removed at exit. Never the real one: that is the +# user's live notification position, and a test must not move it. +tmpstate="$(mktemp)" +trap 'rm -f "$tmpstate"' EXIT +STATE="$tmpstate" + +rm -f "$tmpstate" +check "a missing state file reports no previous revision" \ + "" "$(read_prev_rev "uuid-a")" + +write_state "uuid-a" 500 +check "a revision written is a revision read back" \ + "500" "$(read_prev_rev "uuid-a")" + +check "a different database UUID discards the revision" \ + "" "$(read_prev_rev "uuid-b")" + +printf 'uuid-a garbage\n' > "$tmpstate" +check "an unparseable state file reports no previous revision" \ + "" "$(read_prev_rev "uuid-a")" + +write_state "uuid-a" 600 +check "a rewrite replaces rather than appends" \ + "1" "$(wc -l < "$tmpstate")" + +printf '\n%d passed, %d failed\n' "$pass" "$fail" +[[ "$fail" -eq 0 ]] |
