Skip to content

Commit bd16ea8

Browse files
committed
✅ Add modal tests
Signed-off-by: Paillat-dev <[email protected]>
1 parent 3169cc6 commit bd16ea8

File tree

1 file changed

+202
-0
lines changed

1 file changed

+202
-0
lines changed

tests/test_components.py

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
"""
2+
The MIT License (MIT)
3+
4+
Copyright (c) 2021-present Pycord Development
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a
7+
copy of this software and associated documentation files (the "Software"),
8+
to deal in the Software without restriction, including without limitation
9+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
10+
and/or sell copies of the Software, and to permit persons to whom the
11+
Software is furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22+
DEALINGS IN THE SOFTWARE.
23+
"""
24+
25+
from typing import Any
26+
import pytest
27+
import random
28+
import string
29+
30+
from discord import components
31+
import discord
32+
33+
random.seed(42)
34+
35+
def random_string(
36+
min_len, max_len, spaces: bool = True, punctuation: bool = True, separators: tuple[str, ...] = ("-", "_")
37+
):
38+
chars = string.ascii_letters + string.digits
39+
if spaces:
40+
chars += " "
41+
if punctuation:
42+
chars += string.punctuation
43+
if separators:
44+
chars += "".join(separators)
45+
return "".join(random.choices(chars, k=random.randint(min_len, max_len)))
46+
47+
48+
def generate_test_user_select_modal(
49+
*,
50+
modal_title: str,
51+
modal_custom_id: str,
52+
label_title: str,
53+
label_description: str,
54+
select_default_user_id: int,
55+
select_custom_id: str,
56+
):
57+
MODAL: components.Modal = components.Modal(
58+
components.Label(
59+
components.UserSelect(
60+
default_values=[components.DefaultSelectOption(id=select_default_user_id, type="user")],
61+
custom_id=select_custom_id,
62+
),
63+
label=label_title,
64+
description=label_description,
65+
),
66+
title=modal_title,
67+
custom_id=modal_custom_id,
68+
)
69+
EXPECTED_PAYLOAD = {
70+
"title": modal_title, # 1-45 characters
71+
"custom_id": modal_custom_id, # 1-100 characters
72+
"components": [
73+
{
74+
"type": 18,
75+
"label": label_title, # 1-45 characters
76+
"description": label_description, # 1-100 characters
77+
"id": None,
78+
"component": {
79+
"type": 5,
80+
"custom_id": select_custom_id, # int64
81+
"default_values": [
82+
{
83+
"id": select_default_user_id, # int64
84+
"type": "user",
85+
}
86+
],
87+
"id": None,
88+
"max_values": 1,
89+
"min_values": 1,
90+
},
91+
}
92+
],
93+
}
94+
95+
return MODAL, EXPECTED_PAYLOAD
96+
97+
USER_SELECT_MODAL_CASES = [
98+
generate_test_user_select_modal(
99+
modal_title=random_string(1, 45),
100+
modal_custom_id=random_string(1, 100),
101+
label_title=random_string(1, 45),
102+
label_description=random_string(1, 100),
103+
select_default_user_id=random.randint(100000000000000000, 999999999999999999),
104+
select_custom_id=random_string(1, 100),
105+
)
106+
for _ in range(10)
107+
]
108+
@pytest.mark.parametrize(
109+
("modal", "payload"),
110+
USER_SELECT_MODAL_CASES,
111+
)
112+
def test_user_select_modal_to_dict(
113+
modal: components.Modal,
114+
payload: dict[Any, Any],
115+
):
116+
# Test that the modal generates the expected payload
117+
assert modal.to_dict() == payload
118+
119+
def generate_test_text_input_modal(
120+
*,
121+
modal_title: str,
122+
modal_custom_id: str,
123+
label_title: str,
124+
label_description: str,
125+
text_input_custom_id: str,
126+
text_input_value: str,
127+
text_input_placeholder: str,
128+
text_input_min_length: int,
129+
text_input_max_length: int,
130+
text_input_required: bool,
131+
text_input_multiline: bool,
132+
):
133+
MODAL: components.Modal = components.Modal(
134+
components.Label(
135+
components.TextInput(
136+
custom_id=text_input_custom_id,
137+
value=text_input_value,
138+
placeholder=text_input_placeholder,
139+
min_length=text_input_min_length,
140+
max_length=text_input_max_length,
141+
required=text_input_required,
142+
style=discord.TextInputStyle.paragraph if text_input_multiline else discord.TextInputStyle.short,
143+
),
144+
label=label_title,
145+
description=label_description,
146+
),
147+
title=modal_title,
148+
custom_id=modal_custom_id,
149+
)
150+
EXPECTED_PAYLOAD = {
151+
"title": modal_title, # 1-45 characters
152+
"custom_id": modal_custom_id, # 1-100 characters
153+
"components": [
154+
{
155+
"type": 18,
156+
"label": label_title, # 1-45 characters
157+
"description": label_description, # 1-100 characters
158+
"id": None,
159+
"component": {
160+
"type": 4,
161+
"custom_id": text_input_custom_id, # 1-100 characters
162+
"value": text_input_value, # 0-4000 characters
163+
"placeholder": text_input_placeholder, # 0-100 characters
164+
"min_length": text_input_min_length, # 0-4000
165+
"max_length": text_input_max_length, # 1-4000
166+
"style": 2 if text_input_multiline else 1,
167+
"id": None,
168+
},
169+
}
170+
],
171+
}
172+
if not text_input_required:
173+
EXPECTED_PAYLOAD["components"][0]["component"]["required"] = False # pyright: ignore[reportArgumentType]
174+
175+
return MODAL, EXPECTED_PAYLOAD
176+
177+
TEXT_INPUT_MODAL_CASES = [
178+
generate_test_text_input_modal(
179+
modal_title=random_string(1, 45),
180+
modal_custom_id=random_string(1, 100),
181+
label_title=random_string(1, 45),
182+
label_description=random_string(1, 100),
183+
text_input_custom_id=random_string(1, 100),
184+
text_input_value=random_string(1, 4000),
185+
text_input_placeholder=random_string(1, 100),
186+
text_input_min_length=random.randint(0, 4000),
187+
text_input_max_length=random.randint(1, 4000),
188+
text_input_required=random.choice([True, False]),
189+
text_input_multiline=random.choice([True, False]),
190+
)
191+
for _ in range(10)
192+
]
193+
@pytest.mark.parametrize(
194+
("modal", "payload"),
195+
TEXT_INPUT_MODAL_CASES,
196+
)
197+
def test_text_input_modal_to_dict(
198+
modal: components.Modal,
199+
payload: dict[Any, Any],
200+
):
201+
# Test that the modal generates the expected payload
202+
assert modal.to_dict() == payload

0 commit comments

Comments
 (0)