123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- from functools import reduce
- from unittest.mock import Mock
- import pytest
- from typer.testing import CliRunner
- from reflex.reflex import cli
- from reflex.utils.hosting import DeploymentPrepInfo
- runner = CliRunner()
- def test_login_success_existing_token(mocker):
- mocker.patch(
- "reflex.utils.hosting.authenticated_token",
- return_value=("fake-token", "fake-code"),
- )
- result = runner.invoke(cli, ["login"])
- assert result.exit_code == 0
- def test_login_success_on_browser(mocker):
- mocker.patch(
- "reflex.utils.hosting.authenticated_token",
- return_value=("", "fake-code"),
- )
- mock_authenticate_on_browser = mocker.patch(
- "reflex.utils.hosting.authenticate_on_browser", return_value="fake-token"
- )
- result = runner.invoke(cli, ["login"])
- assert result.exit_code == 0
- mock_authenticate_on_browser.assert_called_once_with("fake-code")
- def test_login_fail(mocker):
- # Access token does not exist, but user authenticates successfully on browser.
- mocker.patch(
- "reflex.utils.hosting.get_existing_access_token", return_value=("", "")
- )
- mocker.patch("reflex.utils.hosting.authenticate_on_browser", return_value="")
- result = runner.invoke(cli, ["login"])
- assert result.exit_code == 1
- @pytest.mark.parametrize(
- "args",
- [
- ["--no-interactive", "-k", "chatroom"],
- ["--no-interactive", "--deployment-key", "chatroom"],
- ["--no-interactive", "-r", "sjc"],
- ["--no-interactive", "--region", "sjc"],
- ["--no-interactive", "-r", "sjc", "-r", "lax"],
- ["--no-interactive", "-r", "sjc", "--region", "lax"],
- ],
- )
- def test_deploy_required_args_missing(args):
- result = runner.invoke(cli, ["deploy", *args])
- assert result.exit_code == 1
- @pytest.fixture
- def setup_env_authentication(mocker):
- mocker.patch("reflex.utils.prerequisites.check_initialized")
- mocker.patch("reflex.utils.hosting.authenticated_token", return_value="fake-token")
- mocker.patch("time.sleep")
- def test_deploy_non_interactive_prepare_failed(
- mocker,
- setup_env_authentication,
- ):
- mocker.patch(
- "reflex.utils.hosting.prepare_deploy",
- side_effect=Exception("server did not like params in prepare"),
- )
- result = runner.invoke(
- cli, ["deploy", "--no-interactive", "-k", "chatroom", "-r", "sjc"]
- )
- assert result.exit_code == 1
- @pytest.mark.parametrize(
- "optional_args,values",
- [
- ([], None),
- (["--env", "k1=v1"], {"envs": {"k1": "v1"}}),
- (["--cpus", 2], {"cpus": 2}),
- (["--memory-mb", 2048], {"memory_mb": 2048}),
- (["--no-auto-start"], {"auto_start": False}),
- (["--no-auto-stop"], {"auto_stop": False}),
- (
- ["--frontend-hostname", "myfrontend.com"],
- {"frontend_hostname": "myfrontend.com"},
- ),
- ],
- )
- def test_deploy_non_interactive_success(
- mocker, setup_env_authentication, optional_args, values
- ):
- mocker.patch("reflex.utils.console.ask")
- app_prefix = "fake-prefix"
- mocker.patch(
- "reflex.utils.hosting.prepare_deploy",
- return_value=Mock(
- app_prefix=app_prefix,
- reply=Mock(
- api_url="fake-api-url", deploy_url="fake-deploy-url", key="fake-key"
- ),
- ),
- )
- fake_export_dir = "fake-export-dir"
- mocker.patch("tempfile.mkdtemp", return_value=fake_export_dir)
- mocker.patch("reflex.reflex.export")
- mock_deploy = mocker.patch(
- "reflex.utils.hosting.deploy",
- return_value=Mock(
- frontend_url="fake-frontend-url", backend_url="fake-backend-url"
- ),
- )
- mocker.patch("reflex.utils.hosting.wait_for_server_to_pick_up_request")
- mocker.patch("reflex.utils.hosting.display_deploy_milestones")
- mocker.patch("reflex.utils.hosting.poll_backend", return_value=True)
- mocker.patch("reflex.utils.hosting.poll_frontend", return_value=True)
- # TODO: typer option default not working in test for app name
- deployment_key = "chatroom-0"
- app_name = "chatroom"
- regions = ["sjc"]
- result = runner.invoke(
- cli,
- [
- "deploy",
- "--no-interactive",
- "-k",
- deployment_key,
- *reduce(lambda x, y: x + ["-r", y], regions, []),
- "--app-name",
- app_name,
- *optional_args,
- ],
- )
- assert result.exit_code == 0
- expected_call_args = dict(
- frontend_file_name="frontend.zip",
- backend_file_name="backend.zip",
- export_dir=fake_export_dir,
- key=deployment_key,
- app_name=app_name,
- regions=regions,
- app_prefix=app_prefix,
- cpus=None,
- memory_mb=None,
- auto_start=None,
- auto_stop=None,
- frontend_hostname=None,
- envs=None,
- with_metrics=None,
- with_tracing=None,
- )
- expected_call_args.update(values or {})
- assert mock_deploy.call_args.kwargs == expected_call_args
- def get_app_prefix():
- return "fake-prefix"
- def get_deployment_key():
- return "i-want-this-site"
- def get_suggested_key():
- return "suggested-key"
- def test_deploy_interactive_prepare_failed(
- mocker,
- setup_env_authentication,
- ):
- mocker.patch(
- "reflex.utils.hosting.prepare_deploy",
- side_effect=Exception("server did not like params in prepare"),
- )
- result = runner.invoke(cli, ["deploy"])
- assert result.exit_code == 1
- @pytest.mark.parametrize(
- "app_prefix,deployment_key,prepare_responses,user_input_region,user_input_envs,expected_key,args_patch",
- [
- # CLI provides suggestion and but user enters a different key
- (
- get_app_prefix(),
- get_deployment_key(),
- Mock(
- app_prefix=get_app_prefix(),
- reply=None,
- suggestion=Mock(
- api_url="fake-api-url",
- deploy_url="fake-deploy-url",
- key=get_suggested_key(),
- ),
- existing=None,
- enabled_regions=["sjc"],
- ),
- ["sjc"],
- [],
- get_deployment_key(),
- None,
- ),
- # CLI provides suggestion and but user enters a different key and enters envs
- (
- get_app_prefix(),
- get_deployment_key(),
- Mock(
- app_prefix=get_app_prefix(),
- reply=None,
- suggestion=Mock(
- api_url="fake-api-url",
- deploy_url="fake-deploy-url",
- key=get_suggested_key(),
- ),
- existing=None,
- enabled_regions=["sjc"],
- ),
- ["sjc"],
- ["k1=v1", "k2=v2"],
- get_deployment_key(),
- {"envs": {"k1": "v1", "k2": "v2"}},
- ),
- # CLI provides suggestion and but user takes it
- (
- get_app_prefix(),
- get_deployment_key(),
- Mock(
- app_prefix=get_app_prefix(),
- reply=None,
- suggestion=Mock(
- api_url="fake-api-url",
- deploy_url="fake-deploy-url",
- key=get_suggested_key(),
- ),
- existing=None,
- enabled_regions=["sjc"],
- ),
- ["sjc"],
- [],
- get_suggested_key(),
- None,
- ),
- # CLI provides suggestion and but user takes it and enters envs
- (
- get_app_prefix(),
- get_deployment_key(),
- Mock(
- app_prefix=get_app_prefix(),
- reply=None,
- suggestion=Mock(
- api_url="fake-api-url",
- deploy_url="fake-deploy-url",
- key=get_suggested_key(),
- ),
- existing=None,
- enabled_regions=["sjc"],
- ),
- ["sjc"],
- ["k1=v1", "k3=v3"],
- get_suggested_key(),
- {"envs": {"k1": "v1", "k3": "v3"}},
- ),
- # User has an existing deployment
- (
- get_app_prefix(),
- get_deployment_key(),
- Mock(
- app_prefix=get_app_prefix(),
- reply=None,
- existing=Mock(
- __getitem__=lambda _, __: DeploymentPrepInfo(
- api_url="fake-api-url",
- deploy_url="fake-deploy-url",
- key=get_deployment_key(),
- )
- ),
- suggestion=None,
- enabled_regions=["sjc"],
- ),
- ["sjc"],
- [],
- get_deployment_key(),
- None,
- ),
- # User has an existing deployment then updates the envs
- (
- get_app_prefix(),
- get_deployment_key(),
- Mock(
- app_prefix=get_app_prefix(),
- reply=None,
- existing=Mock(
- __getitem__=lambda _, __: DeploymentPrepInfo(
- api_url="fake-api-url",
- deploy_url="fake-deploy-url",
- key=get_deployment_key(),
- )
- ),
- suggestion=None,
- enabled_regions=["sjc"],
- ),
- ["sjc"],
- ["k4=v4"],
- get_deployment_key(),
- {"envs": {"k4": "v4"}},
- ),
- ],
- )
- def test_deploy_interactive(
- mocker,
- setup_env_authentication,
- app_prefix,
- deployment_key,
- prepare_responses,
- user_input_region,
- user_input_envs,
- expected_key,
- args_patch,
- ):
- mocker.patch(
- "reflex.utils.hosting.check_requirements_for_non_reflex_packages",
- return_value=True,
- )
- mocker.patch(
- "reflex.utils.hosting.prepare_deploy",
- return_value=prepare_responses,
- )
- mocker.patch(
- "reflex.utils.hosting.interactive_get_deployment_key_from_user_input",
- return_value=(expected_key, "fake-api-url", "fake-deploy-url"),
- )
- mocker.patch("reflex.utils.console.ask", side_effect=user_input_region)
- mocker.patch(
- "reflex.utils.hosting.interactive_prompt_for_envs", return_value=user_input_envs
- )
- fake_export_dir = "fake-export-dir"
- mocker.patch("tempfile.mkdtemp", return_value=fake_export_dir)
- mocker.patch("reflex.reflex.export")
- mock_deploy = mocker.patch(
- "reflex.utils.hosting.deploy",
- return_value=Mock(
- frontend_url="fake-frontend-url", backend_url="fake-backend-url"
- ),
- )
- mocker.patch("reflex.utils.hosting.wait_for_server_to_pick_up_request")
- mocker.patch("reflex.utils.hosting.display_deploy_milestones")
- mocker.patch("reflex.utils.hosting.poll_backend", return_value=True)
- mocker.patch("reflex.utils.hosting.poll_frontend", return_value=True)
- # TODO: typer option default not working in test for app name
- app_name = "fake-app-workaround"
- regions = ["sjc"]
- result = runner.invoke(
- cli,
- ["deploy", "--app-name", app_name],
- )
- assert result.exit_code == 0
- expected_call_args = dict(
- frontend_file_name="frontend.zip",
- backend_file_name="backend.zip",
- export_dir=fake_export_dir,
- key=expected_key,
- app_name=app_name,
- regions=regions,
- app_prefix=app_prefix,
- cpus=None,
- memory_mb=None,
- auto_start=None,
- auto_stop=None,
- frontend_hostname=None,
- envs=None,
- with_metrics=None,
- with_tracing=None,
- )
- expected_call_args.update(args_patch or {})
- assert mock_deploy.call_args.kwargs == expected_call_args
|