File size: 7,002 Bytes
58f00c9
 
6c3a31d
b737d7a
6c3a31d
58f00c9
 
 
 
 
49b8170
 
 
 
 
 
 
 
58f00c9
 
 
 
6c3a31d
 
 
 
 
b737d7a
 
 
 
 
6c3a31d
 
b737d7a
 
58f00c9
6c3a31d
 
58f00c9
 
b737d7a
 
 
58f00c9
b737d7a
 
6c3a31d
b737d7a
6c3a31d
58f00c9
 
b737d7a
 
58f00c9
6c3a31d
 
 
b737d7a
 
6c3a31d
 
b737d7a
6c3a31d
58f00c9
 
b737d7a
 
6c3a31d
58f00c9
b737d7a
 
 
58f00c9
b737d7a
6c3a31d
 
 
58f00c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import pytest

from bot.db import DEFAULT_CAPTION, Database
from bot.formats import FormatSettings
from bot.parser import DEFAULT_TEMPLATE
from bot.settings_ops import META_COMMANDS, META_KINDS, apply_setting, parse_channel, preview_template

UID = 7


@pytest.fixture
async def db(tmp_path):
    d = Database(f"sqlite+aiosqlite:///{tmp_path}/s.db")
    await d.init()
    yield d
    await d.close()


async def get(db):
    return await db.get_settings(UID)


async def auto(db):
    """The auto format in use: the template and the caption are saved there, not in the user's settings."""
    return await db.get_auto_format(UID)


@pytest.fixture
async def store(db):
    """Where the template and the caption are saved: an auto format (they live in formats, not in the user's settings)."""
    fmt = await db.create_format(UID, "Default", kind="auto")
    return FormatSettings(db, fmt["id"])


async def test_template_saved_with_preview(db, store):
    ok, msg = await apply_setting(store, UID, "template", "[S{season}E{episode}] {title} [{quality}]")
    assert ok and "Template saved" in msg and "Preview" in msg
    assert (await auto(db))["template"] == "[S{season}E{episode}] {title} [{quality}]"
    assert "template" not in await get(db)  # the user's own settings don't hold one


async def test_template_validation_and_reset(db, store):
    assert (await apply_setting(store, UID, "template", "   "))[0] is False
    ok, msg = await apply_setting(store, UID, "template", "x" * 201)
    assert not ok and "too long" in msg
    assert (await auto(db))["template"] == DEFAULT_TEMPLATE  # nothing was saved
    await apply_setting(store, UID, "template", "{title}")
    assert (await auto(db))["template"] == "{title}"
    ok, _ = await apply_setting(store, UID, "template", "reset")
    assert ok and (await auto(db))["template"] == DEFAULT_TEMPLATE


async def test_template_unknown_variables_are_reported_but_saved(db, store):
    ok, msg = await apply_setting(store, UID, "template", "{title} {nope}")
    assert ok and "{nope}" in msg and "Unknown variables" in msg
    assert (await auto(db))["template"] == "{title} {nope}"


async def test_the_padded_episode_variables_are_known_ones(db, store):
    ok, msg = await apply_setting(store, UID, "template", "{title} E{1episode} {2episode} {3episode}")
    assert ok and "Unknown" not in msg
    assert "Tokyo Revengers E05 005 0005" in msg  # the preview shows the padding
    ok, msg = await apply_setting(store, UID, "caption", "Episode {2episode} of {title}")
    assert ok and "Unknown" not in msg


async def test_caption_set_validate_reset(db, store):
    ok, msg = await apply_setting(store, UID, "caption", "<b>{filename}</b> · {size}")
    assert ok and (await auto(db))["caption"] == "<b>{filename}</b> · {size}"
    assert "Unknown" not in msg
    assert (await apply_setting(store, UID, "caption", "x" * 801))[0] is False
    assert (await apply_setting(store, UID, "caption", ""))[0] is False
    ok, msg = await apply_setting(store, UID, "caption", "{bogus}")
    assert ok and "{bogus}" in msg
    ok, _ = await apply_setting(store, UID, "caption", "reset")
    assert ok and (await auto(db))["caption"] == DEFAULT_CAPTION == "<b>{filename}</b>"


async def test_remove_words(db):
    ok, msg = await apply_setting(db, UID, "remove", "@Chan, [Group]\n www.site.com ,, ")
    assert ok
    assert (await get(db))["remove_words"] == ["@Chan", "[Group]", "www.site.com"]
    assert (await apply_setting(db, UID, "remove", " , ,"))[0] is False
    assert (await apply_setting(db, UID, "remove", ", ".join(f"w{i}" for i in range(51))))[0] is False
    assert (await apply_setting(db, UID, "remove", "x" * 61))[0] is False
    ok, _ = await apply_setting(db, UID, "remove", "off")
    assert ok and (await get(db))["remove_words"] == []


@pytest.mark.parametrize("kind", sorted(META_KINDS))
async def test_every_metadata_field_can_be_set_and_cleared(db, kind):
    field = META_KINDS[kind]
    ok, msg = await apply_setting(db, UID, kind, f"{field} value")
    assert ok and (await get(db))["meta"][field] == f"{field} value"
    assert "Metadata is Off" in msg  # reminder that nothing applies until it is switched on
    await db.update_settings(UID, metadata_on=True)
    ok, msg = await apply_setting(db, UID, kind, "another")
    assert ok and "Metadata is Off" not in msg
    ok, _ = await apply_setting(db, UID, kind, "off")
    assert ok and (await get(db))["meta"][field] == ""


async def test_metadata_value_validation(db):
    assert (await apply_setting(db, UID, "mt_title", ""))[0] is False
    ok, msg = await apply_setting(db, UID, "mt_title", "x" * 201)
    assert not ok and "too long" in msg
    assert (await get(db))["meta"]["title"] == ""


async def test_meta_commands_map_to_known_kinds():
    assert set(META_COMMANDS.values()) == set(META_KINDS)


async def test_metadata_values_are_html_escaped_in_the_reply(db):
    ok, msg = await apply_setting(db, UID, "mt_title", "<script>")
    assert ok and "<script>" not in msg and "&lt;script&gt;" in msg


@pytest.mark.parametrize("kind", ["keep_audio", "keep_subtitle"])
async def test_keep_tracks_by_language_names_keeps_order_and_enables_metadata(db, kind):
    assert (await get(db))["metadata_on"] is False
    ok, msg = await apply_setting(db, UID, kind, "English, Japanese")
    assert ok
    s = await get(db)
    assert s[kind] == ["english", "japanese"]
    assert s["metadata_on"] is True and "turned it On" in msg
    ok, msg = await apply_setting(db, UID, kind, "2 1")
    assert ok and (await get(db))[kind] == ["2", "1"] and "turned it On" not in msg
    ok, msg = await apply_setting(db, UID, kind, "off")
    assert ok and (await get(db))[kind] == [] and "all tracks are kept" in msg


async def test_keep_tracks_rejects_bad_input_without_changing_anything(db):
    await apply_setting(db, UID, "keep_audio", "english")
    for bad in ("0", "1 english 0", "***", "   ", "a" * 30, "1 2 3 4 5 6 7 8 9 10 11 12 13"):
        ok, msg = await apply_setting(db, UID, "keep_audio", bad)
        assert not ok and msg.startswith("❌"), bad
        assert (await get(db))["keep_audio"] == ["english"]


async def test_keep_tracks_duplicates_are_collapsed(db):
    await apply_setting(db, UID, "keep_audio", "english eng English 2 2")
    assert (await get(db))["keep_audio"] == ["english", "eng", "2"]


async def test_unknown_kind_raises(db):
    with pytest.raises(ValueError):
        await apply_setting(db, UID, "nonsense", "x")


def test_parse_channel():
    assert parse_channel("-1001234567890") == (True, -1001234567890, "")
    assert parse_channel("12345") == (True, 12345, "")
    assert parse_channel("off") == (True, None, "")
    ok, cid, err = parse_channel("@mychannel")
    assert not ok and cid is None and "numeric" in err
    assert parse_channel("12")[0] is False


def test_preview_template_renders_sample():
    out = preview_template("{title} [{quality}]")
    assert "Preview" in out and "<code>" in out and "[" in out