Skip to content

Commit dc7ef54

Browse files
authored
♻️ Prompt user for login or waitlist option when not logged in (#81)
* Update * Add tests * Update
1 parent 892d4b9 commit dc7ef54

3 files changed

Lines changed: 91 additions & 5 deletions

File tree

src/fastapi_cloud_cli/commands/deploy.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from rich_toolkit.menu import Option
2121
from typing_extensions import Annotated
2222

23+
from fastapi_cloud_cli.commands.login import login
2324
from fastapi_cloud_cli.utils.api import APIClient
2425
from fastapi_cloud_cli.utils.apps import AppConfig, get_app_config, write_app_config
2526
from fastapi_cloud_cli.utils.auth import is_logged_in
@@ -556,10 +557,33 @@ def deploy(
556557

557558
with get_rich_toolkit() as toolkit:
558559
if not is_logged_in():
559-
logger.debug("User not logged in, showing waitlist form")
560-
_waitlist_form(toolkit)
560+
logger.debug("User not logged in, prompting for login or waitlist")
561561

562-
raise typer.Exit(1)
562+
toolkit.print_title("Welcome to FastAPI Cloud!", tag="FastAPI")
563+
toolkit.print_line()
564+
565+
toolkit.print(
566+
"You need to be logged in to deploy to FastAPI Cloud.",
567+
tag="info",
568+
)
569+
toolkit.print_line()
570+
571+
choice = toolkit.ask(
572+
"What would you like to do?",
573+
tag="auth",
574+
options=[
575+
Option({"name": "Login to my existing account", "value": "login"}),
576+
Option({"name": "Join the waiting list", "value": "waitlist"}),
577+
],
578+
)
579+
580+
toolkit.print_line()
581+
582+
if choice == "login":
583+
login()
584+
else:
585+
_waitlist_form(toolkit)
586+
raise typer.Exit(1)
563587

564588
toolkit.print_title("Starting deployment", tag="FastAPI")
565589
toolkit.print_line()

tests/test_cli_deploy.py

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,63 @@ def _get_random_deployment(
6060

6161

6262
@pytest.mark.respx(base_url=settings.base_api_url)
63-
def test_shows_waitlist_form_when_not_logged_in(
63+
def test_chooses_login_option_when_not_logged_in(
6464
logged_out_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
6565
) -> None:
66-
steps = [*"some@example.com", Keys.ENTER, Keys.RIGHT_ARROW, Keys.ENTER, Keys.ENTER]
66+
steps = [Keys.ENTER]
67+
68+
respx_mock.post(
69+
"/login/device/authorization", data={"client_id": settings.client_id}
70+
).mock(
71+
return_value=Response(
72+
200,
73+
json={
74+
"verification_uri_complete": "http://test.com",
75+
"verification_uri": "http://test.com",
76+
"user_code": "1234",
77+
"device_code": "5678",
78+
},
79+
)
80+
)
81+
respx_mock.post(
82+
"/login/device/token",
83+
data={
84+
"device_code": "5678",
85+
"client_id": settings.client_id,
86+
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
87+
},
88+
).mock(return_value=Response(200, json={"access_token": "test_token_1234"}))
89+
90+
with changing_dir(tmp_path), patch(
91+
"rich_toolkit.container.getchar"
92+
) as mock_getchar, patch(
93+
"fastapi_cloud_cli.commands.login.typer.launch"
94+
) as mock_launch:
95+
mock_getchar.side_effect = steps
96+
97+
result = runner.invoke(app, ["deploy"])
98+
99+
assert "Welcome to FastAPI Cloud!" in result.output
100+
assert "What would you like to do?" in result.output
101+
assert "Login to my existing account" in result.output
102+
assert "Join the waiting list" in result.output
103+
assert "Now you are logged in!" in result.output
104+
assert mock_launch.called
105+
106+
107+
@pytest.mark.respx(base_url=settings.base_api_url)
108+
def test_chooses_waitlist_option_when_not_logged_in(
109+
logged_out_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
110+
) -> None:
111+
steps = [
112+
Keys.DOWN_ARROW,
113+
Keys.ENTER,
114+
*"some@example.com",
115+
Keys.ENTER,
116+
Keys.RIGHT_ARROW,
117+
Keys.ENTER,
118+
Keys.ENTER,
119+
]
67120

68121
respx_mock.post(
69122
"/users/waiting-list",
@@ -87,6 +140,10 @@ def test_shows_waitlist_form_when_not_logged_in(
87140
result = runner.invoke(app, ["deploy"])
88141

89142
assert result.exit_code == 1
143+
assert "Welcome to FastAPI Cloud!" in result.output
144+
assert "What would you like to do?" in result.output
145+
assert "Login to my existing account" in result.output
146+
assert "Join the waiting list" in result.output
90147
assert "We're currently in private beta" in result.output
91148
assert "Let's go! Thanks for your interest in FastAPI Cloud! 🚀" in result.output
92149

@@ -96,6 +153,8 @@ def test_shows_waitlist_form_when_not_logged_in_longer_flow(
96153
logged_out_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
97154
) -> None:
98155
steps = [
156+
Keys.DOWN_ARROW, # Select "Join the waiting list"
157+
Keys.ENTER,
99158
*"some@example.com",
100159
Keys.ENTER,
101160
Keys.ENTER,
@@ -767,6 +826,8 @@ def test_shows_error_for_invalid_waitlist_form_data(
767826
logged_out_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
768827
) -> None:
769828
steps = [
829+
Keys.DOWN_ARROW, # Select "Join the waiting list"
830+
Keys.ENTER,
770831
*"test@example.com",
771832
Keys.ENTER,
772833
Keys.ENTER, # Choose to provide more information

tests/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def changing_dir(directory: Union[str, Path]) -> Generator[None, None, None]:
1616

1717
class Keys:
1818
RIGHT_ARROW = "\x1b[C"
19+
DOWN_ARROW = "\x1b[B"
1920
ENTER = "\r"
2021
CTRL_C = "\x03"
2122
TAB = "\t"

0 commit comments

Comments
 (0)