- Snooze (with a Snoozed folder), keyboard shortcuts with a Settings section, mail templates (Compose > More > Templates), a Subscriptions folder with bulk unsubscribe/delete, and tracker blocking with a Privacy toggle (on by default) - Own dialogs instead of browser popups; emoji picker in compose; compose windows survive a visit to Settings - Sentence completion learned from the user's sent mail (no AI) - Interface in English and Polish (one file per language, English as the fallback), picked from the browser on first run, then kept - Email translation on the server via LibreTranslate: Translate button and "Translate to...", messages in several languages translated part by part, names/addresses/emoji/file names/phone numbers kept, an animated line while translating - Antispam "Mark as spam" loads with the message, not when the menu opens Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
42 lines
1.6 KiB
Python
42 lines
1.6 KiB
Python
"""Sentence completion over the API, from the user's sent mail."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from app.api import completion as api_completion
|
|
from app.completion import build_index_job
|
|
from tests.api.conftest import HDR, MailCtx, raw_mail
|
|
|
|
|
|
async def _suggest(ctx: MailCtx, before: str) -> str | None:
|
|
resp = await ctx.client.post("/api/completion", json={"before": before}, headers=HDR)
|
|
assert resp.status_code == 200, resp.text
|
|
return resp.json()["suggestion"]
|
|
|
|
|
|
async def test_suggests_from_sent_mail(mail_ctx: MailCtx, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
queued: list[tuple[Any, ...]] = []
|
|
|
|
async def fake_enqueue(name: str, *args: Any, **kwargs: Any) -> None:
|
|
queued.append((name, *args))
|
|
|
|
monkeypatch.setattr(api_completion, "enqueue_job", fake_enqueue)
|
|
body = "Hi Anna,\nThe renders will be ready by Thursday evening.\n\nOn Mon Anna wrote:\n> ok"
|
|
for uid in (1, 2):
|
|
await mail_ctx.deliver(
|
|
raw_mail("Renders", sender="me@example.com").replace(b"Renders body", body.encode()),
|
|
uid,
|
|
folder="sent",
|
|
)
|
|
|
|
# No index yet: a build is asked for, and the starter phrases still answer.
|
|
assert await _suggest(mail_ctx, "I look forward ") == "to hearing from you."
|
|
assert queued and queued[0][0] == "build_index_job"
|
|
|
|
assert await build_index_job({}, str(mail_ctx.user_id)) > 0
|
|
assert await _suggest(mail_ctx, "The renders will be re") == "ady by Thursday evening."
|
|
assert await _suggest(mail_ctx, "> ok") is None # quoted text was not learned
|