Skip to content

Commit 3529bb4

Browse files
Merge pull request #460 from supertokens/test/email-link
test: adds test for `create_reset_password_link`
2 parents d5ebe65 + 8c4aaee commit 3529bb4

File tree

2 files changed

+210
-3
lines changed

2 files changed

+210
-3
lines changed

tests/emailpassword/test_passwordreset.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,20 @@
1414
import asyncio
1515
import json
1616
from typing import Any, Dict, Union
17+
from urllib.parse import urlparse
1718

1819
from fastapi import FastAPI
1920
from fastapi.requests import Request
2021
from fastapi.testclient import TestClient
21-
from pytest import fixture, mark
22+
from pytest import fixture, mark, raises
2223
from supertokens_python import InputAppInfo, SupertokensConfig, init
24+
from supertokens_python.exceptions import GeneralError
2325
from supertokens_python.framework.fastapi import get_middleware
2426
from supertokens_python.recipe import emailpassword, session
27+
from supertokens_python.recipe.emailpassword.asyncio import create_reset_password_link
28+
from supertokens_python.recipe.emailpassword.interfaces import (
29+
CreateResetPasswordLinkUnknownUserIdError,
30+
)
2531
from supertokens_python.recipe.session import SessionContainer
2632
from supertokens_python.recipe.session.asyncio import (
2733
create_new_session,
@@ -124,6 +130,7 @@ async def test_that_generated_password_link_is_correct(
124130
reset_url = None
125131
token_info: Union[None, str] = None
126132
rid_info: Union[None, str] = None
133+
tenant_info: Union[None, str] = None
127134

128135
class CustomEmailService(
129136
emailpassword.EmailDeliveryInterface[emailpassword.EmailTemplateVars]
@@ -133,11 +140,12 @@ async def send_email(
133140
template_vars: emailpassword.EmailTemplateVars,
134141
user_context: Dict[str, Any],
135142
) -> None:
136-
nonlocal reset_url, token_info, rid_info
143+
nonlocal reset_url, token_info, rid_info, tenant_info
137144
password_reset_url_with_token = template_vars.password_reset_link
138145
reset_url = password_reset_url_with_token.split("?")[0]
139146
token_info = password_reset_url_with_token.split("?")[1].split("&")[0]
140147
rid_info = password_reset_url_with_token.split("?")[1].split("&")[1]
148+
tenant_info = password_reset_url_with_token.split("?")[1].split("&")[2]
141149

142150
init(
143151
supertokens_config=SupertokensConfig("http://localhost:3567"),
@@ -172,6 +180,7 @@ async def send_email(
172180
assert reset_url == "http://supertokens.io/auth/reset-password"
173181
assert token_info is not None and "token=" in token_info # type: ignore pylint: disable=unsupported-membership-test
174182
assert rid_info is not None and "rid=emailpassword" in rid_info # type: ignore pylint: disable=unsupported-membership-test
183+
assert tenant_info is not None and "tenantId=public" in tenant_info # type: ignore pylint: disable=unsupported-membership-test
175184

176185

177186
@mark.asyncio
@@ -258,6 +267,14 @@ async def send_email(
258267
token_info = (
259268
password_reset_url_with_token.split("?")[1].split("&")[0].split("=")[1]
260269
)
270+
assert (
271+
password_reset_url_with_token.split("?")[1].split("&")[2].split("=")[1]
272+
== "public"
273+
)
274+
assert (
275+
password_reset_url_with_token.split("?")[1].split("&")[1].split("=")[1]
276+
== "emailpassword"
277+
)
261278

262279
init(
263280
supertokens_config=SupertokensConfig("http://localhost:3567"),
@@ -339,3 +356,46 @@ async def send_email(
339356
assert dict_response["status"] == "OK"
340357
assert dict_response["user"]["id"] == user_info["id"]
341358
assert dict_response["user"]["email"] == user_info["email"]
359+
360+
361+
@mark.asyncio
362+
async def test_create_reset_password_link(
363+
driver_config_client: TestClient,
364+
):
365+
init(
366+
supertokens_config=SupertokensConfig("http://localhost:3567"),
367+
app_info=InputAppInfo(
368+
app_name="SuperTokens Demo",
369+
api_domain="http://api.supertokens.io",
370+
website_domain="http://supertokens.io",
371+
api_base_path="/auth",
372+
),
373+
framework="fastapi",
374+
recipe_list=[
375+
emailpassword.init(),
376+
session.init(get_token_transfer_method=lambda _, __, ___: "cookie"),
377+
],
378+
)
379+
start_st()
380+
381+
response_1 = sign_up_request(
382+
driver_config_client, "[email protected]", "validpass123"
383+
)
384+
assert response_1.status_code == 200
385+
dict_response = json.loads(response_1.text)
386+
user_info = dict_response["user"]
387+
assert dict_response["status"] == "OK"
388+
link = await create_reset_password_link("public", user_info["id"])
389+
url = urlparse(link.link) # type: ignore
390+
queries = url.query.strip("&").split("&")
391+
assert url.path == "/auth/reset-password"
392+
assert "token=" in queries[0]
393+
assert "tenantId=public" in queries
394+
assert "rid=emailpassword" in queries
395+
396+
link = await create_reset_password_link("public", "invalidUserId")
397+
assert isinstance(link, CreateResetPasswordLinkUnknownUserIdError)
398+
399+
with raises(GeneralError) as err:
400+
await create_reset_password_link("invalidTenantId", user_info["id"])
401+
assert "status code: 400" in str(err.value)

tests/thirdpartyemailpassword/test_email_delivery.py

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
from fastapi import FastAPI
2121
from fastapi.requests import Request
2222
from fastapi.testclient import TestClient
23-
from pytest import fixture, mark
23+
from pytest import fixture, mark, raises
24+
from urllib.parse import urlparse
2425

2526
from supertokens_python import InputAppInfo, SupertokensConfig, init
27+
from supertokens_python.exceptions import GeneralError
2628
from supertokens_python.framework.fastapi import get_middleware
2729
from supertokens_python.ingredients.emaildelivery import EmailDeliveryInterface
2830
from supertokens_python.ingredients.emaildelivery.types import (
@@ -37,6 +39,15 @@
3739
session,
3840
thirdpartyemailpassword,
3941
)
42+
from supertokens_python.recipe.thirdpartyemailpassword.asyncio import (
43+
create_reset_password_link,
44+
send_reset_password_email,
45+
)
46+
from supertokens_python.recipe.thirdpartyemailpassword.interfaces import (
47+
CreateResetPasswordLinkUnknownUserIdError,
48+
SendResetPasswordEmailEmailOkResult,
49+
SendResetPasswordEmailUnknownUserIdError,
50+
)
4051
from supertokens_python.recipe.emailverification.emaildelivery.services import (
4152
SMTPService as EVSMTPService,
4253
)
@@ -1036,3 +1047,139 @@ async def send_email(
10361047

10371048
assert email == "[email protected]"
10381049
assert email_verify_url != ""
1050+
1051+
1052+
@mark.asyncio
1053+
async def test_create_reset_password_link(
1054+
driver_config_client: TestClient,
1055+
):
1056+
init(
1057+
supertokens_config=SupertokensConfig("http://localhost:3567"),
1058+
app_info=InputAppInfo(
1059+
app_name="SuperTokens Demo",
1060+
api_domain="http://api.supertokens.io",
1061+
website_domain="http://supertokens.io",
1062+
api_base_path="/auth",
1063+
),
1064+
framework="fastapi",
1065+
recipe_list=[
1066+
thirdpartyemailpassword.init(),
1067+
session.init(get_token_transfer_method=lambda _, __, ___: "cookie"),
1068+
],
1069+
)
1070+
start_st()
1071+
1072+
response_1 = sign_up_request(
1073+
driver_config_client, "[email protected]", "validpass123"
1074+
)
1075+
assert response_1.status_code == 200
1076+
dict_response = json.loads(response_1.text)
1077+
user_info = dict_response["user"]
1078+
assert dict_response["status"] == "OK"
1079+
link = await create_reset_password_link("public", user_info["id"])
1080+
url = urlparse(link.link) # type: ignore
1081+
queries = url.query.strip("&").split("&")
1082+
assert url.path == "/auth/reset-password"
1083+
assert "tenantId=public" in queries
1084+
assert "rid=thirdpartyemailpassword" in queries
1085+
1086+
link = await create_reset_password_link("public", "invalidUserId")
1087+
assert isinstance(link, CreateResetPasswordLinkUnknownUserIdError)
1088+
1089+
with raises(GeneralError) as err:
1090+
await create_reset_password_link("invalidTenantId", user_info["id"])
1091+
assert "status code: 400" in str(err.value)
1092+
1093+
1094+
@mark.asyncio
1095+
async def test_send_reset_password_email(
1096+
driver_config_client: TestClient,
1097+
):
1098+
1099+
tenant_info, token_info, rid_info, reset_url = "", "", "", ""
1100+
1101+
class CustomEmailDeliveryService(
1102+
thirdpartyemailpassword.EmailDeliveryInterface[PasswordResetEmailTemplateVars]
1103+
):
1104+
async def send_email(
1105+
self,
1106+
template_vars: PasswordResetEmailTemplateVars,
1107+
user_context: Dict[str, Any],
1108+
):
1109+
nonlocal reset_url, token_info, rid_info, tenant_info
1110+
password_reset_url = template_vars.password_reset_link
1111+
reset_url = password_reset_url.split("?")[0]
1112+
token_info = password_reset_url.split("?")[1].split("&")[0]
1113+
rid_info = password_reset_url.split("?")[1].split("&")[1]
1114+
tenant_info = password_reset_url.split("?")[1].split("&")[2]
1115+
1116+
init(
1117+
supertokens_config=SupertokensConfig("http://localhost:3567"),
1118+
app_info=InputAppInfo(
1119+
app_name="SuperTokens Demo",
1120+
api_domain="http://api.supertokens.io",
1121+
website_domain="http://supertokens.io",
1122+
api_base_path="/auth",
1123+
),
1124+
framework="fastapi",
1125+
recipe_list=[
1126+
thirdpartyemailpassword.init(
1127+
email_delivery=thirdpartyemailpassword.EmailDeliveryConfig(
1128+
CustomEmailDeliveryService()
1129+
)
1130+
),
1131+
session.init(get_token_transfer_method=lambda _, __, ___: "cookie"),
1132+
],
1133+
)
1134+
start_st()
1135+
1136+
response_1 = sign_up_request(
1137+
driver_config_client, "[email protected]", "validpass123"
1138+
)
1139+
assert response_1.status_code == 200
1140+
dict_response = json.loads(response_1.text)
1141+
user_info = dict_response["user"]
1142+
assert dict_response["status"] == "OK"
1143+
resp = await send_reset_password_email("public", user_info["id"])
1144+
assert isinstance(resp, SendResetPasswordEmailEmailOkResult)
1145+
1146+
assert reset_url == "http://supertokens.io/auth/reset-password"
1147+
assert token_info is not None and "token=" in token_info
1148+
assert rid_info is not None and "rid=thirdpartyemailpassword" in rid_info
1149+
assert tenant_info is not None and "tenantId=public" in tenant_info
1150+
1151+
1152+
@mark.asyncio
1153+
async def test_send_reset_password_email_invalid_input(
1154+
driver_config_client: TestClient,
1155+
):
1156+
1157+
init(
1158+
supertokens_config=SupertokensConfig("http://localhost:3567"),
1159+
app_info=InputAppInfo(
1160+
app_name="SuperTokens Demo",
1161+
api_domain="http://api.supertokens.io",
1162+
website_domain="http://supertokens.io",
1163+
api_base_path="/auth",
1164+
),
1165+
framework="fastapi",
1166+
recipe_list=[
1167+
thirdpartyemailpassword.init(),
1168+
session.init(get_token_transfer_method=lambda _, __, ___: "cookie"),
1169+
],
1170+
)
1171+
start_st()
1172+
1173+
response_1 = sign_up_request(
1174+
driver_config_client, "[email protected]", "validpass123"
1175+
)
1176+
assert response_1.status_code == 200
1177+
dict_response = json.loads(response_1.text)
1178+
user_info = dict_response["user"]
1179+
1180+
link = await send_reset_password_email("public", "invalidUserId")
1181+
assert isinstance(link, SendResetPasswordEmailUnknownUserIdError)
1182+
1183+
with raises(GeneralError) as err:
1184+
await send_reset_password_email("invalidTenantId", user_info["id"])
1185+
assert "status code: 400" in str(err.value)

0 commit comments

Comments
 (0)