disnake

Форк
0
/
test_embeds.py 
482 строки · 13.7 Кб
1
# SPDX-License-Identifier: MIT
2

3
import io
4
from datetime import datetime, timedelta
5

6
import pytest
7

8
from disnake import Color, Embed, File, embeds
9
from disnake.utils import MISSING, utcnow
10

11
_BASE = {"type": "rich"}
12

13

14
@pytest.fixture
15
def embed() -> Embed:
16
    time = utcnow() + timedelta(days=42)
17
    return Embed(
18
        type="link",
19
        title="wow",
20
        description="what a cool embed",
21
        url="http://endless.horse",
22
        timestamp=time,
23
        color=0xF8A8B8,
24
    )
25

26

27
@pytest.fixture
28
def file() -> File:
29
    return File(io.BytesIO(b"abcd"), filename="data.txt")
30

31

32
def test_init_empty() -> None:
33
    embed = Embed()
34
    assert embed.title is None
35
    assert embed.description is None
36
    assert embed.url is None
37
    assert embed.timestamp is None
38

39
    assert embed.to_dict() == _BASE
40
    assert not bool(embed)
41

42
    assert embed.fields == []
43

44

45
def test_init_all(embed: Embed) -> None:
46
    assert embed.timestamp
47
    assert embed.to_dict() == {
48
        "type": "link",
49
        "title": "wow",
50
        "description": "what a cool embed",
51
        "url": "http://endless.horse",
52
        "timestamp": embed.timestamp.isoformat(),
53
        "color": 0xF8A8B8,
54
    }
55
    assert bool(embed)
56

57

58
def test_type_default() -> None:
59
    # type for new embeds should be set to default value
60
    assert Embed().type == "rich"
61

62
    # type shouldn't be set in from_dict if dict didn't contain a type
63
    assert Embed.from_dict({}).type is None
64

65

66
def test_timestamp_naive(embed: Embed) -> None:
67
    embed.timestamp = datetime.now()  # noqa: DTZ005  # the point of this is to test naive dts
68
    assert embed.timestamp.tzinfo is not None
69

70

71
def test_len(embed: Embed) -> None:
72
    assert len(embed) == 20
73

74
    embed.set_footer(text="hmm", icon_url="https://localhost")
75
    assert len(embed) == 23
76

77
    embed.set_author(name="someone", url="https://127.0.0.1", icon_url="https://127.0.0.2")
78
    assert len(embed) == 30
79

80
    embed.add_field("field name", "field value")
81
    embed.add_field("another field", "woooo")
82
    assert len(embed) == 69
83

84

85
def test_eq() -> None:
86
    # basic test
87
    embed_1, embed_2 = Embed(), Embed()
88
    assert embed_1 == embed_2
89

90
    embed_1.title, embed_2.title = None, ""
91
    assert embed_1 == embed_2
92

93
    # color tests
94
    embed_1, embed_2 = Embed(), Embed()
95
    embed_1.color = Color(123456)
96
    assert not embed_1 == embed_2
97

98
    embed_1.color = MISSING
99
    assert embed_1 == embed_2
100

101
    embed_1, embed_2 = Embed(color=None), Embed()
102
    assert embed_1 == embed_2
103

104
    try:
105
        Embed.set_default_color(123456)
106
        assert not embed_1 == embed_2
107
    finally:
108
        Embed.set_default_color(None)
109

110
    # test fields
111
    embed_1, embed_2 = Embed(), Embed()
112
    embed_1.add_field(name="This is a test field", value="69 test 69")
113
    embed_2.add_field(name="This is a test field", value="69 test 69", inline=False)
114
    assert not embed_1 == embed_2
115

116
    embed_1, embed_2 = Embed(), Embed()
117
    embed_1._fields = []
118
    embed_2._fields = None
119
    assert embed_1 == embed_2
120

121

122
def test_embed_proxy_eq() -> None:
123
    embed_1, embed_2 = Embed(), Embed()
124

125
    embed_1.set_image("https://disnake.dev/assets/disnake-logo.png")
126
    embed_2.set_image(None)
127
    assert not embed_1.image == embed_2.image
128

129
    embed_2.set_image("https://disnake.dev/assets/disnake-logo.png")
130
    assert embed_1.image == embed_2.image
131

132

133
def test_color_zero() -> None:
134
    e = Embed()
135
    assert not e
136

137
    # color=0 should be applied to to_dict, __bool__, and __eq__
138
    e.color = 0
139
    assert e
140
    assert e.to_dict() == {"color": 0, **_BASE}
141
    assert e != Embed(color=None)
142

143

144
def test_default_color() -> None:
145
    try:
146
        # color applies if set before init
147
        Embed.set_default_color(123456)
148
        embed = Embed()
149
        assert embed.color == Color(123456)
150

151
        # default color should not affect __bool__
152
        assert not bool(embed)
153

154
        # custom value overrides default
155
        embed.color = 987654
156
        assert embed.color == Color(987654)
157
        assert embed.to_dict() == {"color": 987654, **_BASE}
158
        assert bool(embed)
159

160
        # removing custom value resets to default
161
        del embed.color
162
        assert embed.color == Color(123456)
163

164
        # clearing default changes color to `None`
165
        Embed.set_default_color(None)
166
        assert embed.color is None
167
    finally:
168
        Embed.set_default_color(None)
169

170

171
def test_default_color_copy(embed: Embed) -> None:
172
    # copy should retain color
173
    assert embed.copy().color == Color(0xF8A8B8)
174

175
    del embed.color
176
    assert embed.copy().color is None
177

178
    try:
179
        # copying with default value should not set attribute
180
        Embed.set_default_color(123456)
181
        c = embed.copy()
182
        assert c._colour is MISSING
183

184
        assert c.color == Color(123456)
185
    finally:
186
        Embed.set_default_color(None)
187

188

189
def test_attr_proxy() -> None:
190
    embed = Embed()
191
    author = embed.author
192
    assert len(author) == 0
193

194
    embed.set_author(name="someone")
195
    author = embed.author
196
    assert len(author) == 1
197
    assert author.name == "someone"
198
    assert embed.to_dict() == {"author": {"name": "someone"}, **_BASE}
199
    assert author.icon_url is None
200

201
    embed.set_author(name="abc", icon_url="https://xyz")
202
    assert len(embed.author) == 2
203

204
    embed.remove_author()
205
    assert len(embed.author) == 0
206
    assert embed.to_dict() == _BASE
207

208

209
def test_image_init() -> None:
210
    # should be empty initially
211
    embed = Embed()
212
    assert embed._files == {}
213
    assert embed.to_dict() == _BASE
214

215

216
def test_image_none() -> None:
217
    # removing image shouldn't change dict
218
    embed = Embed()
219
    embed.set_image(None)
220
    assert embed._files == {}
221
    assert embed.to_dict() == _BASE
222

223

224
def test_image_url() -> None:
225
    embed = Embed()
226
    embed.set_image("https://disnake.dev")
227
    assert embed._files == {}
228
    assert embed.to_dict() == {"image": {"url": "https://disnake.dev"}, **_BASE}
229

230

231
def test_image_file(file: File) -> None:
232
    embed = Embed()
233
    embed.set_image(file=file)
234
    assert embed._files == {"image": file}
235
    assert embed.to_dict() == {"image": {"url": "attachment://data.txt"}, **_BASE}
236

237

238
def test_image_remove(file: File) -> None:
239
    embed = Embed()
240
    embed.set_image(file=file)
241
    embed.set_image(None)
242
    assert embed._files == {}
243
    assert embed.to_dict() == _BASE
244

245

246
def test_file_params(file: File) -> None:
247
    embed = Embed()
248
    with pytest.raises(TypeError):
249
        embed.set_image("https://disnake.dev/assets/disnake-logo.png", file=file)  # type: ignore
250

251
    assert embed._files == {}
252
    assert embed.to_dict() == _BASE
253

254

255
def test_file_filename(file: File) -> None:
256
    embed = Embed()
257
    file.filename = None
258
    with pytest.raises(TypeError):
259
        embed.set_image(file=file)
260

261

262
def test_file_overwrite_url(file: File) -> None:
263
    embed = Embed()
264
    # setting url should remove file
265
    embed.set_image(file=file)
266
    embed.set_image("https://abc")
267
    assert embed._files == {}
268
    assert embed.to_dict() == {"image": {"url": "https://abc"}, **_BASE}
269

270

271
def test_file_overwrite_file(file: File) -> None:
272
    embed = Embed()
273
    # setting file twice should keep second one
274
    file2 = File(io.BytesIO(), filename="empty.dat")
275
    embed.set_image(file=file)
276
    embed.set_image(file=file2)
277
    assert embed._files == {"image": file2}
278
    assert embed.to_dict() == {"image": {"url": "attachment://empty.dat"}, **_BASE}
279

280

281
def test_file_multiple(file: File) -> None:
282
    embed = Embed()
283
    # setting multiple files should work correctly
284
    embed.set_image(file=file)
285
    embed.set_thumbnail(file=file)
286
    assert embed._files == {"image": file, "thumbnail": file}
287
    assert embed.to_dict() == {
288
        "image": {"url": "attachment://data.txt"},
289
        "thumbnail": {"url": "attachment://data.txt"},
290
        **_BASE,
291
    }
292

293

294
def test_fields() -> None:
295
    embed = Embed()
296

297
    embed.insert_field_at(42, "a", "b")
298
    assert embed.to_dict() == {"fields": [{"name": "a", "value": "b", "inline": True}], **_BASE}
299

300
    embed.insert_field_at(0, "c", "d")
301
    assert embed.to_dict() == {
302
        "fields": [
303
            {"name": "c", "value": "d", "inline": True},
304
            {"name": "a", "value": "b", "inline": True},
305
        ],
306
        **_BASE,
307
    }
308

309
    embed.set_field_at(-1, "e", "f", inline=False)
310
    assert embed.to_dict() == {
311
        "fields": [
312
            {"name": "c", "value": "d", "inline": True},
313
            {"name": "e", "value": "f", "inline": False},
314
        ],
315
        **_BASE,
316
    }
317

318
    embed.remove_field(0)
319
    assert embed.to_dict() == {"fields": [{"name": "e", "value": "f", "inline": False}], **_BASE}
320

321
    embed.clear_fields()
322
    assert embed.to_dict() == _BASE
323

324

325
def test_fields_exceptions() -> None:
326
    embed = Embed()
327

328
    # shouldn't raise
329
    embed.remove_field(42)
330

331
    # also shouldn't raise
332
    embed.add_field("a", "b")
333
    embed.remove_field(5)
334

335
    with pytest.raises(IndexError):
336
        embed.set_field_at(42, "x", "y")
337

338
    embed.clear_fields()
339
    with pytest.raises(IndexError):
340
        embed.set_field_at(0, "x", "y")
341

342

343
def test_field_restraints() -> None:
344
    embed = Embed(title="T" * 256)  # Size = 256
345
    embed.set_footer(text="T" * 2048)  # Size = 2304
346
    embed.add_field(name="A" * 256, value="B" * 1024)  # Size = 3584
347
    embed.add_field(name="A" * 256, value="B" * 1024)  # Size = 4864
348
    embed.add_field(name="A" * 112, value="B" * 1024)  # Size = 6000
349
    assert len(embed) == 6000
350
    embed.check_limits()
351

352
    embed.add_field(name="A", value="B")  # Breaks limit of 6000 chars
353
    with pytest.raises(ValueError, match="^Embed total size"):
354
        embed.check_limits()
355
    embed.remove_field(3)
356

357
    embed.check_limits()
358
    embed.insert_field_at(index=3, name="A", value="B")  # Breaks limit of 6000 chars
359
    with pytest.raises(ValueError, match="^Embed total size"):
360
        embed.check_limits()
361
    embed.remove_field(3)
362

363
    embed.set_field_at(index=2, name="A" * 113, value="B" * 1024)  # Breaks limit of 6000 chars
364
    assert len(embed) == 6001
365
    with pytest.raises(ValueError, match="^Embed total size"):
366
        embed.check_limits()
367
    embed.set_field_at(index=2, name="A" * 112, value="B" * 1024)
368
    assert len(embed) == 6000
369

370
    embed.set_author(name="A")  # Breaks limit of 6000 chars
371
    with pytest.raises(ValueError, match="^Embed total size"):
372
        embed.check_limits()
373
    embed.remove_author()
374

375
    embed.set_footer(
376
        text="T" * 2048 + " " * 500
377
    )  # Would break the 6000 limit, but leading + trailing whitespace doesn't count
378
    embed.check_limits()
379

380
    embed = Embed(title="Too many fields :WAYTOODANK:")
381
    for _ in range(25):
382
        embed.add_field(name="OK", value=":D")
383
    embed.check_limits()
384

385
    embed.add_field(name="NOTOK", value="D:")
386
    with pytest.raises(ValueError, match="Embeds cannot have more than 25 fields"):
387
        embed.check_limits()
388

389
    embed = Embed(title="author_check")
390
    embed.set_author(name="A" * 256)
391
    embed.check_limits()
392
    embed.set_author(name="B" * 257)
393
    with pytest.raises(ValueError, match="^Embed author"):
394
        embed.check_limits()
395

396
    embed = Embed(title="footer_check")
397
    embed.set_footer(text="A" * 2048)
398
    embed.check_limits()
399
    embed.set_footer(text="B" * 2049)
400
    with pytest.raises(ValueError, match="^Embed footer"):
401
        embed.check_limits()
402

403
    embed = Embed(title="title_check" + "A" * 245)
404
    embed.check_limits()
405
    embed = Embed(title="title_check" + "A" * 246)
406
    with pytest.raises(ValueError, match="^Embed title"):
407
        embed.check_limits()
408

409
    embed = Embed(description="desc_check" + "A" * 4086)
410
    embed.check_limits()
411
    embed = Embed(description="desc_check" + "A" * 4087)
412
    with pytest.raises(ValueError, match="^Embed description"):
413
        embed.check_limits()
414

415

416
def test_copy(embed: Embed, file: File) -> None:
417
    embed.set_footer(text="hi there", icon_url="https://localhost")
418
    embed.set_author(name="someone", url="https://127.0.0.1", icon_url="https://127.0.0.2")
419
    embed.add_field("field name", "field value")
420
    embed.add_field("another field", "woooo")
421
    embed.set_thumbnail("https://thumbnail.url")
422
    embed.set_image(file=file)
423

424
    # copying should keep exact dict representation
425
    copy = embed.copy()
426
    assert embed.to_dict() == copy.to_dict()
427

428
    # shallow copy, but `_files` and `_fields` should be copied
429
    assert embed._files == copy._files
430
    assert embed._files is not copy._files
431
    assert embed._fields == copy._fields
432
    assert embed._fields is not copy._fields
433

434

435
def test_copy_empty() -> None:
436
    e = Embed.from_dict({})
437
    copy = e.copy()
438
    assert e.to_dict() == copy.to_dict() == {}
439

440
    # shallow copy, but `_files` and `_fields` should be copied
441
    assert e._files == copy._files
442
    assert e._files is not copy._files
443
    assert e._fields is None
444
    assert copy._fields is None
445

446

447
def test_copy_fields(embed: Embed) -> None:
448
    embed.add_field("things", "stuff")
449
    copy = embed.copy()
450
    embed.clear_fields()
451
    assert copy._fields
452

453
    embed.insert_field_at(0, "w", "x")
454
    copy = embed.copy()
455
    embed.remove_field(0)
456
    assert embed._fields == []
457
    assert copy._fields == [{"name": "w", "value": "x", "inline": True}]
458

459
    embed.insert_field_at(0, "w", "x")
460
    copy = embed.copy()
461
    embed.insert_field_at(1, "y", "z")
462
    embed.set_field_at(0, "abc", "def", inline=False)
463

464
    assert embed._fields == [
465
        {"name": "abc", "value": "def", "inline": False},
466
        {"name": "y", "value": "z", "inline": True},
467
    ]
468
    assert copy._fields == [{"name": "w", "value": "x", "inline": True}]
469

470

471
# backwards compatibility
472
def test_emptyembed() -> None:
473
    with pytest.warns(DeprecationWarning):
474
        assert embeds.EmptyEmbed is None  # type: ignore
475
    with pytest.warns(DeprecationWarning):
476
        assert Embed.Empty is None  # type: ignore
477
    with pytest.warns(DeprecationWarning):
478
        assert Embed().Empty is None  # type: ignore
479

480
    # make sure unknown module attrs continue to raise
481
    with pytest.raises(AttributeError):
482
        _ = embeds.this_does_not_exist  # type: ignore
483

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.