Skip to content

Commit cc4fe92

Browse files
authored
Merge pull request #6 from jpizquierdo/validation-url-contact-fix
Fix validation error in vCard when website is requested
2 parents 516be35 + 5f8fc1d commit cc4fe92

File tree

2 files changed

+45
-28
lines changed

2 files changed

+45
-28
lines changed

app/app.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,27 +126,34 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
126126
elif user_state == UserState.AWAITING_TITLE:
127127
context.user_data["title"] = update.message.text
128128
context.user_data["state"] = UserState.AWAITING_WEBSITE
129-
await update.message.reply_text("Please send the URL 🔗:")
129+
await update.message.reply_text("Please send the Website URL 🔗:")
130130
elif user_state == UserState.AWAITING_WEBSITE:
131-
qr_code = await generate_contact_qr(
132-
ContactQR(
133-
name=context.user_data["name"],
134-
surname=context.user_data["surname"],
135-
phone_number=context.user_data["phone_number"],
136-
email=context.user_data["email"],
137-
company=context.user_data["company"],
138-
title=context.user_data["title"],
139-
url=update.message.text.strip(),
131+
try:
132+
qr_code = await generate_contact_qr(
133+
ContactQR(
134+
name=context.user_data["name"],
135+
surname=context.user_data["surname"],
136+
phone_number=context.user_data["phone_number"],
137+
email=context.user_data["email"],
138+
company=context.user_data["company"],
139+
title=context.user_data["title"],
140+
url=update.message.text.strip(),
141+
)
140142
)
141-
)
143+
except ValidationError:
144+
await update.message.reply_text(
145+
"❌ Invalid URL. Please send a valid URL starting with 'http://' or 'https://'."
146+
)
147+
return None
148+
142149
await update.message.reply_photo(
143150
photo=qr_code, caption="📇 Scan to read de vcard 📞"
144151
)
145152
context.user_data.clear()
146153
await command_options(update, context)
147154

148155
else: # pragma: no cover
149-
logger.error("❌ Invalid state. Please try again.")
156+
logger.debug("❌ Invalid state. Please try again.")
150157
await command_options(update, context)
151158

152159

@@ -174,7 +181,6 @@ async def command_options(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
174181
async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
175182
query = update.callback_query
176183
await query.answer()
177-
178184
if query.data == "contact_info":
179185
await query.message.reply_text("Please send the name:")
180186
context.user_data["state"] = UserState.AWAITING_NAME

tests/test_handle_message.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from app.app import handle_message
55
from app.core.models import UserState, URLQR, WifiQR, ContactQR
66
from app.qrcodegen import generate_wifi_qr, generate_contact_qr, generate_url_qr
7-
from pydantic import ValidationError
7+
88

99
@pytest.mark.asyncio
1010
async def test_handle_message_awaiting_url():
@@ -32,6 +32,7 @@ async def test_handle_message_awaiting_url():
3232
photo=actual_call, caption="Here is your QR code!"
3333
)
3434

35+
3536
@pytest.mark.asyncio
3637
async def test_handle_message_awaiting_url_invalid():
3738

@@ -41,13 +42,15 @@ async def test_handle_message_awaiting_url_invalid():
4142
context.user_data = {"state": UserState.AWAITING_URL}
4243
test_url = "invalid-url.com"
4344
update.message.text = test_url
44-
45+
4546
await handle_message(update, context)
46-
assert(context.user_data["state"]==UserState.AWAITING_URL)
47-
# Assert that the bot sends an error message
47+
assert context.user_data["state"] == UserState.AWAITING_URL
48+
# Assert that the bot sends an error message
4849
update.message.reply_text.assert_called_once_with(
4950
"❌ Invalid URL. Please send a valid URL starting with 'http://' or 'https://'."
5051
)
52+
53+
5154
@pytest.mark.asyncio
5255
async def test_handle_message_awaiting_ssid():
5356
# Mock Update and Context
@@ -66,6 +69,8 @@ async def test_handle_message_awaiting_ssid():
6669

6770
# Assert that the state is updated
6871
assert context.user_data["state"] == UserState.AWAITING_PASSWORD
72+
73+
6974
@pytest.mark.asyncio
7075
async def test_handle_message_awaiting_ssid_invalid():
7176

@@ -75,14 +80,15 @@ async def test_handle_message_awaiting_ssid_invalid():
7580
context.user_data = {"state": UserState.AWAITING_SSID}
7681
test_ssid = "TestSSIDTestSSIDTestSSIDTestSSIDTestSSIDTestSSIDTestSSIDTestSSIDTestSSIDTestSSIDTestSSIDTestSSID"
7782
update.message.text = test_ssid
78-
83+
7984
await handle_message(update, context)
80-
assert(context.user_data["state"]==UserState.AWAITING_SSID)
81-
# Assert that the bot sends an error message
85+
assert context.user_data["state"] == UserState.AWAITING_SSID
86+
# Assert that the bot sends an error message
8287
update.message.reply_text.assert_called_once_with(
8388
"❌ Invalid SSID. Please send a valid SSID (1-32 characters)."
8489
)
8590

91+
8692
@pytest.mark.asyncio
8793
async def test_handle_message_awaiting_password():
8894
# Mock Update and Context
@@ -110,6 +116,8 @@ async def test_handle_message_awaiting_password():
110116
assert context.user_data == {}
111117
# Assert by content
112118
assert update.message.reply_photo.call_count == 1
119+
120+
113121
@pytest.mark.asyncio
114122
async def test_handle_message_awaiting_password_invalid():
115123

@@ -119,14 +127,15 @@ async def test_handle_message_awaiting_password_invalid():
119127
context.user_data = {"state": UserState.AWAITING_PASSWORD, "ssid": "TestSSID"}
120128
test_password = "T"
121129
update.message.text = test_password
122-
130+
123131
await handle_message(update, context)
124-
assert(context.user_data["state"]==UserState.AWAITING_PASSWORD)
125-
# Assert that the bot sends an error message
132+
assert context.user_data["state"] == UserState.AWAITING_PASSWORD
133+
# Assert that the bot sends an error message
126134
update.message.reply_text.assert_called_once_with(
127135
"❌ Invalid SSID or Password. Please send a valid SSID (1-32 characters) and a Valid Password between 8 and 63 characters."
128136
)
129137

138+
130139
@pytest.mark.asyncio
131140
async def test_handle_message_awaiting_name():
132141
# Mock Update and Context
@@ -221,6 +230,7 @@ async def test_handle_message_awaiting_email():
221230
assert context.user_data["state"] == UserState.AWAITING_COMPANY
222231
assert context.user_data["email"] == test_email
223232

233+
224234
@pytest.mark.asyncio
225235
async def test_handle_message_awaiting_email_invalid():
226236

@@ -235,13 +245,15 @@ async def test_handle_message_awaiting_email_invalid():
235245
}
236246
test_email = "joelperez91.gmail.com"
237247
update.message.text = test_email
238-
248+
239249
await handle_message(update, context)
240-
assert(context.user_data["state"]==UserState.AWAITING_EMAIL)
241-
# Assert that the bot sends an error message
250+
assert context.user_data["state"] == UserState.AWAITING_EMAIL
251+
# Assert that the bot sends an error message
242252
update.message.reply_text.assert_called_once_with(
243253
"❌ Invalid email. Please send a valid email address."
244254
)
255+
256+
245257
@pytest.mark.asyncio
246258
async def test_handle_message_awaiting_company():
247259
# Mock Update and Context
@@ -290,7 +302,7 @@ async def test_handle_message_awaiting_title():
290302
await handle_message(update, context)
291303

292304
# Assert that the bot asks for the website URL
293-
update.message.reply_text.assert_called_once_with("Please send the URL 🔗:")
305+
update.message.reply_text.assert_called_once_with("Please send the Website URL 🔗:")
294306

295307
# Assert that the state is updated
296308
assert context.user_data["state"] == UserState.AWAITING_WEBSITE
@@ -343,4 +355,3 @@ async def test_handle_message_awaiting_website():
343355
)
344356
# Assert that user data is cleared
345357
assert context.user_data == {}
346-

0 commit comments

Comments
 (0)