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